Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
89.57% covered (success)
89.57%
3119 / 3482
66.67% covered (success)
66.67%
28 / 42
CRAP
0.00% covered (danger)
0.00%
0 / 1
AppController
89.57% covered (success)
89.57%
3119 / 3482
66.67% covered (success)
66.67%
28 / 42
2439.60
0.00% covered (danger)
0.00%
0 / 1
 beforeFilter
63.13% covered (success)
63.13%
512 / 811
0.00% covered (danger)
0.00%
0 / 1
8213.89
 setLocalization
88.32% covered (success)
88.32%
121 / 137
0.00% covered (danger)
0.00%
0 / 1
130.63
 redirectUsingIpLang
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
1 / 1
6
 redirect
95.00% covered (success)
95.00%
38 / 40
0.00% covered (danger)
0.00%
0 / 1
26
 setConfigLanguage
100.00% covered (success)
100.00%
27 / 27
100.00% covered (success)
100.00%
1 / 1
10
 jpyOnlyPage
100.00% covered (success)
100.00%
33 / 33
100.00% covered (success)
100.00%
1 / 1
13
 checkIfAllowed
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
6
 getTimezoneData
94.23% covered (success)
94.23%
49 / 52
0.00% covered (danger)
0.00%
0 / 1
15.04
 chargePayPalPaymentReceivable
99.00% covered (success)
99.00%
298 / 301
0.00% covered (danger)
0.00%
0 / 1
65
 chargePaymentReceivable
95.52% covered (success)
95.52%
64 / 67
0.00% covered (danger)
0.00%
0 / 1
14
 wpChargePaymentReceivable
97.75% covered (success)
97.75%
87 / 89
0.00% covered (danger)
0.00%
0 / 1
17
 setSeoLocalizeUrl
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 getCustomCurrencyCode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
5
 getPremiumPlanPrice
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
5
 checkStasapuDomain
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
5
 disablePageForSapuri
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
8
 blockWithdrawnSapuriToS
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
11
 createEnglishHubCookie
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
10
 checkControllerActionExist
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
5
 checkIfSNSShare
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
7
 setUpAppreciationSelectionModalElement
100.00% covered (success)
100.00%
56 / 56
100.00% covered (success)
100.00%
1 / 1
24
 sendTeacherAppreciation
100.00% covered (success)
100.00%
39 / 39
100.00% covered (success)
100.00%
1 / 1
14
 isLocalizeDirValid
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 chargeAfteePaymentReceivable
96.13% covered (success)
96.13%
298 / 310
0.00% covered (danger)
0.00%
0 / 1
63
 checkAfteeSupported
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
25
 queryGuideControl
100.00% covered (success)
100.00%
54 / 54
100.00% covered (success)
100.00%
1 / 1
4
 queryLineHoverControl
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
1 / 1
3
 NCPlusPositionUrlScheme
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 checkLitePlanSupported
100.00% covered (success)
100.00%
35 / 35
100.00% covered (success)
100.00%
1 / 1
27
 resetPresetTextbook
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
1 / 1
4
 setPaypalUser
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
6
 checkStripeSupported
100.00% covered (success)
100.00%
41 / 41
100.00% covered (success)
100.00%
1 / 1
34
 processChildReceivablePayment
99.22% covered (success)
99.22%
127 / 128
0.00% covered (danger)
0.00%
0 / 1
20
 processChildPaypalPayment
99.12% covered (success)
99.12%
226 / 228
0.00% covered (danger)
0.00%
0 / 1
22
 processChildAfteePayment
99.55% covered (success)
99.55%
223 / 224
0.00% covered (danger)
0.00%
0 / 1
28
 processParentReceivablePayment
99.20% covered (success)
99.20%
124 / 125
0.00% covered (danger)
0.00%
0 / 1
19
 processParentPaypalPayment
95.54% covered (success)
95.54%
214 / 224
0.00% covered (danger)
0.00%
0 / 1
22
 savePaypalFailedSettlement
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
5
 processParentAfteePayment
96.40% covered (success)
96.40%
214 / 222
0.00% covered (danger)
0.00%
0 / 1
24
 checkCompanyIPForSMS
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
2
 setPerMonthSymbol
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
 corporateIpRestrictionLogout
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Application level Controller
4 *
5 * This file is application-wide controller file. You can put all
6 * application-wide controller-related methods here.
7 *
8 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
9 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
10 *
11 * Licensed under The MIT License
12 * For full copyright and license information, please see the LICENSE.txt
13 * Redistributions of files must retain the above copyright notice.
14 *
15 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
16 * @link          http://cakephp.org CakePHP(tm) Project
17 * @package       app.Controller
18 * @since         CakePHP(tm) v 0.2.9
19 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
20 */
21
22App::uses('Controller', 'Controller');
23
24/**
25 * Application Controller
26 *
27 * Add your application-wide methods in the class below, your controllers
28 * will inherit them.
29 *
30 * @package        app.Controller
31 * @link        http://book.cakephp.org/2.0/en/controllers.html#the-app-controller
32 */
33class AppController extends Controller {
34
35    /**
36     * セッションコンポーネント
37     *
38     * @var SessionComponent
39     */
40    var $Session;
41    public $uses = array(
42        'User',
43        'Notification',
44        'DefineMaster',
45        'CountryCode',
46        'LessonOnairsLog',
47        'LessonConnectionSpeedDetail',
48        'CountryCode',
49        'HeyNCUser',
50        'GuideNavigationbarCategory',
51        'GuideNavigationbarContent',
52        'GuideNavigationbarAuthControl',
53        'GuideNavigationbarMembershipControl',
54        'GuideNavigationbarCurrencyControl',
55        'GuideNavigationbarBrowserLangControl',
56        'CorporateActivationManagement',
57        'UsersDetail',
58        'CompCodeUsage',
59        'Corporate',
60        'RyugakuSchoolLineSetting',
61        'TeacherCoinBox',
62        'InhouseIp',
63        'Timezone'
64    );
65    public $helpers = array('Localize');
66    public $ext = '.php';
67    public $sharedUserData = false;
68    public $components = array(
69        'Paginator',
70        'RequestHandler',
71        'DebugKit.Toolbar',
72        'Session',
73        'Cookie',
74        'Auth' => array(
75            'authenticate'=>array(
76                'Form'=>array(
77                    'fields'=>array('username'=>'email','password'=>'password')
78                )
79            ),
80            'loginRedirect' => array('controller' => 'home', 'action' => 'index'),
81            'logoutRedirect' => array('controller' => 'login', 'action' => 'index'),
82            'loginAction' => '/login',
83            'authError' => '再度ログインしなおしてください。',
84            'loginError' => 'メールアドレス、またはパスワードに誤りがあります。'
85        )
86    );
87    public $slackChannel = "";
88    public $mySlack = NULL;
89    private $a8Url = ""; 
90    private $affiliateUrl = ""; // Affiliate url callback
91    public $timeDiff = 0; // default
92    public $timeDiffSecond = 0;
93    public $displayTime = 0;
94    public $utcOffset = "09:00";// default tokyo
95    public $lang_iso = "";
96    public $parentId = NULL;
97    public $localizeDir;
98    public $baseUrl;
99    public $clpip; // NC-7360 : corporate light plan individual payment
100    public $allowedCoupon = false; 
101    public $studySapuriId = NULL; // NC-7922, Stasap toC/toB(old)
102    public $allowedCurrencies;
103    public $isPayPalUser = false;
104    public $isAfteeUser = false;
105    public $mobAppUserData;
106    public $isSNSShare;
107    public $isSNSShareOverseas;
108    public $studentLessonPriorityTimeDelayInSeconds = 0;
109    public $isStudySapuriTosUser = false; # -stasap toS(new) members, flagging
110    public $isStudySapuriUser = false; # -either Stasap toC/toB/toS(new) members, flagging
111    public $isTemporaryPassword = false;
112    public $localizeIPLang;
113    public $isIndividualCorp = false;
114    public $corpStandardPremiumPaymentPlans = [];
115    public $isStripeUser = false;
116    public $isStripeAppleUser = false;
117    public $isStripeGoogleUser = false;
118    public $isSetLineHoverSetting = false;
119    public $userMembershipType = null;
120    public $isWithdrawn = false;
121
122    public function beforeFilter() {
123        $this->Cookie->httpOnly = true;
124
125        /*Configure Path*/
126        App::build(array(
127            'Model'=>array(
128                ROOT.'/lib/Model/Base/',
129                ROOT.'/lib/Model/',
130                ROOT.'/lib/Model/',
131                ROOT.'/lib/Model/Form/'),
132            'Lib'=>array(
133                ROOT.'/lib/Lib/'
134            ),
135            'Vendor'=>array(
136                ROOT.'/lib/Vendor/'
137            )
138        ));
139        
140        /*Autoload Model*/
141        App::import('Model',array('CommonTable'));
142        App::import('Model',array('CourseMaster'));
143        App::import('Model',array('DefineMaster'));
144
145        /*Autoload Lib*/
146        App::uses('myTools','Lib');
147        App::uses('myMailer','Lib');
148        App::uses('myError','Lib');
149        App::uses('myTranslator','Lib');
150        App::uses('myMemcached', 'Lib');
151        App::uses('textbookTemplate', 'Lib');
152        App::uses('mySlack','Lib');
153        App::uses('wpPaymentService','Lib');
154        App::uses('CommonCache','Lib');
155        App::uses('OfficeAccounting','Lib');
156        App::uses('LineMessageBot', 'Lib'); // NJ-37740
157
158        /*Autoload table class*/
159        spl_autoload_register(function($class){
160            $classFile1 = ROOT.'/lib/Model/'.$class.'.php';
161            $classFile2 = ROOT.'/lib/Model/Form/'.$class.'.php';
162            if(is_file($classFile1)){ require_once($classFile1); }
163            if(is_file($classFile2)){ require_once($classFile2); }
164        });
165
166        //*NC-4284: if url has user remove user and redirect
167        $webUrl = $_SERVER['REQUEST_URI'];
168        $this->parseUrl = parse_url($webUrl);
169        $segment = explode('/', $webUrl);
170        $firstSegment = isset($segment[1])? $segment[1]:'';
171        $secondSegment = isset($segment[2])? $segment[2]:'';
172
173        if (!$this->request->is('post') && !$this->request->is('ajax')) {
174            if ($this->Auth->loggedIn()) {
175                // if (!$this->RequestHandler->isMobile() && !$this->isLocalizeDirValid($this->Cookie->read('localizeDir'))) {
176                //     $this->Session->destroy();
177                //     $past = time() - 3600;
178                //     foreach ( $_COOKIE as $key => $value )
179                //     {    
180                //         setcookie( $key, $value, $past, '/' );
181                //     }
182                // }
183            }
184
185            if ($firstSegment == 'user') {
186                # added localize URL
187                if($secondSegment == 'ja') {
188                    $getNewUrl = str_replace("/user/ja/", "", $webUrl);
189                } else {
190                    $getNewUrl = str_replace("/user/", "", $webUrl);
191                }
192                $url = myTools::getUrl() ."/". $getNewUrl;
193
194                $this->log("Redirect : " . $url , "debug");
195                return $this->redirect($url, 301);
196            }
197
198            # added localize URL
199            if ($firstSegment == 'ja') {
200                if ($webUrl == "/ja" && $segment[2] == '') {
201                    $url = myTools::getUrl();
202                } else {
203                    $getNewUrl = str_replace("/ja/", "", $webUrl);
204                    $url = myTools::getUrl() ."/". $getNewUrl;
205                }
206
207                $this->log("Redirect : " . $url , "debug");
208                return $this->redirect($url, 301);
209            }
210        }
211
212        /*Autoload table class*/
213        spl_autoload_register(function($class){
214            $classFile1 = ROOT.'/lib/Model/'.$class.'.php';
215            $classFile2 = ROOT.'/lib/Model/Form/'.$class.'.php';
216            if(is_file($classFile1)){ require_once($classFile1); }
217            if(is_file($classFile2)){ require_once($classFile2); }
218        });
219        
220        // - if maintenance check
221        if (strtolower(trim($this->request->params['controller'])) == "maintenance-check.html") {
222            return false;
223        }
224        
225        //set language to null to avoid overwriting
226        Configure::write('Config.language', NULL);
227
228        /*Autoload Lib*/
229        Configure::load('my');
230        Configure::load('const');
231
232        if($this->Auth->loggedIn()){
233            $user = $this->Auth->user();
234            $localLang = isset($this->request->data['localizeDir']) ? $this->request->data('localizeDir') : $firstSegment;
235            $params = array(
236                'currency_code' => $user['currency_code'] ?? null,
237                'created' => $user['created'] ?? null,
238                'language' => $localLang
239            );
240
241            if($this->User->languageAccessControlCheck($params) && (!in_array($firstSegment, ['access_control', 'login', 'logout']) && !in_array($secondSegment, ['access_control', 'login', 'logout']))){
242                if(in_array($firstSegment, ['zh-tw', 'zh-cn', 'vi'])){
243                    $latestUrl = preg_replace('/\/(zh-tw|zh-cn|vi)\//', '/', $webUrl);
244                    if(!empty($secondSegment)) {
245                        $this->Session->write("latestAccessUrl" , $latestUrl);
246                    } else {
247                        $this->Session->write("latestAccessUrl" , '/');
248                    }
249                }
250                $url = myTools::getUrl() . "/access_control";
251                return $this->redirect($url, 302);
252            }
253        }
254
255        // - memcache declaration
256        $memcached = new myMemcached();
257        
258        //remove trailing slashes only if not post and not ajax
259        if (!$this->request->is('post') && !$this->request->is('ajax')) {
260            $currURLSTR = $this->here;
261            if (substr($currURLSTR, -1) == '/' && $currURLSTR != '/user/') {
262
263                $currURLSTR = rtrim($currURLSTR, '/');
264                //check if theres a GET data to be append
265                if (!empty($_SERVER['QUERY_STRING'])) {
266                    $currURLSTR = $currURLSTR . '?' . $_SERVER['QUERY_STRING'];
267                }
268
269                // if (!$this->RequestHandler->isMobile() && !$this->isLocalizeDirValid($this->Cookie->read('localizeDir'))) {
270                //     $this->log("redirect_debug -> invalid localizeDirectory" . json_encode($this->Cookie->read('localizeDir')) , "debug");
271                //     return $this->redirect('/');
272                // }
273                
274                return $this->redirect(myTools::getUrl() . $currURLSTR, 301);
275            }
276        }
277
278        if(isset($this->params->params['controller']) &&
279            in_array($this->params->params['controller'], array('register', 'spRegister', 'forgot', 'sp')) &&
280            isset($this->params->params['action']) &&
281            in_array($this->params->params['action'], array('activate_email', 'activate', 'forgotactivate')) &&
282            isset($this->params->params['code'])
283        ) {
284
285            if($this->RequestHandler->isMobile() == false && $this->params->params['controller'] == 'spRegister' && $this->params->params['action'] === 'activate') {
286                return $this->redirect('/register/activate-email/' . $this->params->params['code']);
287            }
288        }
289
290        $paymentPlans = Configure::read('payment_plans');
291        $this->corpStandardPremiumPaymentPlans = [
292            $paymentPlans['corporate_standard_plan'],
293            $paymentPlans['corporate_standard_card_plan'],
294            $paymentPlans['corporate_standard_individual_plan'],
295            $paymentPlans['corporate_premium_plan'],
296            $paymentPlans['corporate_premium_card_plan'],
297            $paymentPlans['corporate_premium_individual_plan']
298        ];
299        $this->set('corpStandardPremiumPaymentPlans', $this->corpStandardPremiumPaymentPlans);
300        $this->set('userCDNPath', Configure::read('user.cdn_path_webroot'));
301        $this->set('userCDNPathV2', Configure::read('user.cdn_path_webroot_v2'));
302        
303        /*Security Check*/
304        $user = $this->Auth->user();
305
306        $skipBeforeFilterActions = Configure::read('skipped_actions_before_filter');  // NJ-47850: Define the actions to skip the beforeFilter
307        // NJ-47850: Get the current controller and action
308        $currentController = $this->name;
309        $currentAction = $this->action;
310        
311        // Check if the current action should skip the beforeFilter
312        if (isset($skipBeforeFilterActions[$currentController]) && in_array($currentAction, $skipBeforeFilterActions[$currentController])) {
313            $datetime = time();
314            
315            if(isset($user) && !empty($user['id'])){
316                $memcachedTimeDiff = $memcached->get('user-timediff-' . $user['id']);
317
318                if (isset($memcachedTimeDiff['timeDiff']) || isset($memcachedTimeDiff['utc'])) {
319                    $this->timeDiff = isset($memcachedTimeDiff['timeDiff']) && is_numeric($memcachedTimeDiff['timeDiff']) ? $memcachedTimeDiff['timeDiff'] : 0;
320                    $this->utcOffset = $memcachedTimeDiff['utc'];
321                    $this->displayTime = $this->Timezone->getUserTime(array('timeDiff' => $this->timeDiff));
322                }else{
323                    $this->displayTime = $datetime;
324                }
325            }else{
326                $this->displayTime = $datetime;
327            }
328            
329            return false;
330        }
331        // end NJ-47850
332        
333        /*meta title*/
334        $meta = Configure::read('my.meta.'.strtolower($this->name));
335        if (!$meta) {
336            $meta = Configure::read('my.meta.'.strtolower($this->action));
337        }
338        if (!$meta) {
339            $meta = Configure::read('my.meta.'.strtolower($this->name).'-'.strtolower($this->action));
340        }
341        if (!empty($meta['title'])) {
342            $this->set('title_for_layout',$meta['title']);
343        }
344        if (!empty($meta['keywords'])) {
345            $this->set('meta_keywords',$meta['keywords']);
346        }
347        if (!empty($meta['description'])) {
348            $this->set('meta_description',$meta['description']);
349        }
350
351        if (!$this->Auth->loggedIn() && $this->Cookie->read('rememberMe') && !$this->RequestHandler->isMobile()) {
352            $cookie = $this->Cookie->read('rememberMe');
353            $this->User->openDBReplica();
354            $this->User->recursive = -1;
355            $data = $this->User->findByEmailAndPassword(myTools::decode($cookie['ae']),myTools::decode($cookie['ap']));
356            $this->User->closeDBReplica();
357            if ($data) {
358                $this->Auth->login($data['User']);
359                if (!$this->RequestHandler->isMobile()) {
360                    return $this->redirect(myTools::getUrl() . '/user/mypage');
361                }
362            }
363        }
364
365        $hideA8 = false;
366        $hideEngHub = false;
367        $engHubCookieIndexStr = null;
368        if (!$this->Auth->loggedIn()) {
369            $cookieTime = Configure::read("cookieTime");            
370            if (isset($this->request->query['cc']) && $this->request->query['cc'] != '') {
371                //extract prefix from cc
372                $cc = explode('_', $this->request->query['cc']);
373                $prefix = isset($cc[0]) ? trim(strtolower($cc[0])) : false;
374                if ($prefix == 'fr') {
375                    // NJ-6146 Check campaign code is FR -> auto redirect to FR_CP
376                    if (isset($cc[1]) && strtolower($cc[1]) != 'cp') {
377                        $query = $this->request->query;
378                        $cc[0] = 'FR_CP';
379                        $query['cc'] = implode('_', $cc);
380                        $query_string = http_build_query($query);
381
382                        $url = $this->here . '?' . $query_string;
383
384                        // $this->log("Redirect : " . $url , "debug");
385
386                        return $this->redirect(myTools::getUrl() . $url, 301);
387                    }
388                    // log
389                    $this->log("[REFERRAL] saving referral code '".$this->request->query['cc']."'' to Cookie! ", "debug");    
390                }
391                
392                $this->Cookie->write('campaign_code', $this->request->query['cc'], true, $cookieTime);
393            }
394            
395            //save cookie a8 identification
396            if (isset($this->request->query['a8']) && !empty($this->request->query['a8'])) {
397                $this->Cookie->write('a8_id', $this->request->query['a8'], true, $cookieTime);
398            }
399
400            // NC-8916 - Generate english hub cookie
401            $engHubCookieIndexStr = $this->createEnglishHubCookie();
402
403            // NJ-26035 - save cookie for google cloud id 
404            if (
405                (isset($this->request->query['gclid']) && !empty($this->request->query['gclid']))
406            ) {
407            
408                $googleCloudCookie = $this->Cookie->read('gclid');
409
410                // - save the cookie if not yet saved
411                if (!$googleCloudCookie) {
412                    $this->Cookie->write('gclid', $this->request->query['gclid'], true, $cookieTime);
413                }
414
415                // - save the cookie when the saved cookie is not the same as the params google cloud id
416                if (
417                    $googleCloudCookie && 
418                    $googleCloudCookie != $this->request->query['gclid']
419                ) {
420                    $this->Cookie->write('gclid', $this->request->query['gclid'], true, $cookieTime);
421                }
422            }
423
424            //NJ-63077 - save cookie for facebook cloud id and tiktok cloud id
425            if (
426                (isset($this->request->query['fbclid']) && !empty($this->request->query['fbclid'])) || (isset($this->request->query['ttclid']) && !empty($this->request->query['ttclid']))
427            ) {
428            
429                $facebookCloudCookie = $this->Cookie->read('fbclid');
430                $tiktokCloudCookie = $this->Cookie->read('ttclid');
431
432                // - save the cookie if not yet saved
433                if (!$facebookCloudCookie) {
434                    $this->Cookie->write('fbclid', $this->request->query['fbclid'], true, $cookieTime);
435                }
436                
437                if (!$tiktokCloudCookie) {
438                    $this->Cookie->write('ttclid', $this->request->query['ttclid'], true, $cookieTime);
439                }
440
441                // - save the cookie when the saved cookie is not the same as the params google cloud id
442                if (
443                    $facebookCloudCookie && 
444                    $facebookCloudCookie != $this->request->query['fbclid']
445                ) {
446                    $this->Cookie->write('fbclid', $this->request->query['fbclid'], true, $cookieTime);
447                }
448
449                if (
450                    $tiktokCloudCookie && 
451                    $tiktokCloudCookie != $this->request->query['ttclid']
452                ) {
453                    $this->Cookie->write('ttclid', $this->request->query['ttclid'], true, $cookieTime);
454                }
455            }
456            
457            //NJ-63077 - delete other cloud id cookies if one is set
458            if (!empty($this->request->query['gclid'])) {
459                $this->Cookie->delete('fbclid');
460                $this->Cookie->delete('ttclid');
461            } elseif (!empty($this->request->query['fbclid'])) {
462                $this->Cookie->delete('gclid');
463                $this->Cookie->delete('ttclid');
464            } elseif (!empty($this->request->query['ttclid'])) {
465                $this->Cookie->delete('gclid');
466                $this->Cookie->delete('fbclid');
467            }
468
469        } else {
470            //check if complimentary user
471            $complimentary_code = $this->Auth->user('complimentary_code');
472            if (!empty($complimentary_code)) {
473                $hideA8 = true;
474                $hideEngHub = true;
475            }
476        }
477
478        //check a8 exist
479        if ($this->Cookie->check('a8_id') && !$hideA8) {
480            $encodeURL = myTools::getUrl() . '/api/users/purchase_done?a8=' . $this->Cookie->read('a8_id') . '&api_token={partner_parameters}';
481            $this->a8Url = 'event_callback_a967je=' . urlencode($encodeURL);
482            $this->affiliateUrl = $this->a8Url;
483        }
484
485
486        // NC-8916 : check english hub affiliate tracking
487        $ehubCookieIndex = Configure::read('english_hub_affiliate_param.p');
488        if ( $this->Cookie->check($engHubCookieIndexStr) && !$hideEngHub ) {
489            $setcid = $this->Cookie->read($engHubCookieIndexStr);
490            $encodeURL = myTools::getUrl() . '/api/users/purchase_done?cid=' . $setcid . '&api_token={partner_parameters}';
491            $this->affiliateUrl = 'event_callback_a967je=' . urlencode($encodeURL);
492        }
493
494        $this->set('affiliateUrl', $this->affiliateUrl);
495        $this->set('a8Url', $this->a8Url);
496        $this->set('a8_id', $this->Cookie->read('a8_id'));
497
498        //if cookie is not set then detect device then set cookie
499        if(!isset($_COOKIE['viewMode'])) {
500            $device = myTools::getDevice();
501            if ($device == 2 || $device == 3 || $device == 4) {
502                setcookie('viewMode', 'sp', 0, '/');
503            } else {
504                setcookie('viewMode', 'pc', 0, '/');
505            }
506        }
507
508        //NC-4772 [Asia deployment] [Mobapp] 
509        $parentData = $this->User->setConfigLanguage($this->request->query);
510        $this->set('current_lang', $parentData['current_lang']);
511        $this->set('restriction', $parentData['restriction']);
512
513        $this->set('ver', Configure::read('user.version'));
514
515        //get parent_id for family validation
516        $this->parentId = isset($parentData['User']['parent_id']) ? $parentData['User']['parent_id'] : NULL;
517
518        // check if from SNS share        
519        $this->isSNSShare = $this->checkIfSNSShare();
520        $this->isSNSShareOverseas = (isset($_GET["nc_sns_is_overseas"]) && $_GET["nc_sns_is_overseas"] == 1) ? true : false;
521        $this->set('isSNSShare', $this->isSNSShare);
522
523        # NC-7196: LOCALIZE URL
524        $this->localizeDir = Configure::read('default.localization');
525        $this->setLocalization();
526        $this->setSeoLocalizeUrl();
527
528        # NJ-18262 : Guide Control
529        $redis = new myRedis();
530        $guideControlCached = $redis->get("dynamic_global_guide_control");
531        $lineGuideControlCached = $redis->get("dynamic_line_hover_guide_control");
532
533        if (!$guideControlCached){
534            $this->queryGuideControl();
535        } else {
536            $guideNavigationbarCategory = json_decode($redis->get("dynamic_global_guide_control"),true);
537            $this->set('GuideNavigationbarCategory', $guideNavigationbarCategory);
538        }
539
540        if (!$this->isSetLineHoverSetting) {
541            $this->isSetLineHoverSetting = true;
542            $this->queryLineHoverControl();
543        }
544
545        // check if url is from payment kickback "bypass maintenance redirection for zeus and worldpay"
546        $isPayment = in_array(strtolower($this->params['action']), ['zeuspay', 'getwppaymentresult', 'getafteepaymentresult','school_zeuspay','school_zeuspay_bank', 'stripepay', 'stripepay_manual']);
547
548        // - check if maintenance
549        if (!myTools::checkCompanyIP($_SERVER['REMOTE_ADDR']) && !$isPayment) {
550            $maintenance = MaintenanceTable::getMaintenance();
551            if ($maintenance) {
552                // CHECK IF ACCESS TYPE NOT SEO CRAWLER
553                if ( myTools::isCrawler() === FALSE ) {
554                    $controller = strtolower($this->params['controller']);
555                    $action = strtolower($this->params['action']);
556                    if ( $this->Auth->loggedIn() ) {
557                        //$this->log('[NJ-65075] AppController.php L#'.__LINE__.' -- '.json_encode(array('request_data' => $this->request, 'user_agent' => $_SERVER['HTTP_USER_AGENT'])), 'error');
558                        $this->Auth->logout();
559                    }
560
561                    if($controller != 'maintenance' && !in_array($action, array('regular', 'checkmaintenance'))) {
562                        if (
563                            strpos($_SERVER['REQUEST_URI'], "/ko") !== false ||
564                            strpos($_SERVER['REQUEST_URI'], "/zh-tw")  !== false ||
565                            strpos($_SERVER['REQUEST_URI'], "/vi")  !== false
566                        ) {
567                            return $this->redirect('/../maintenance/regular');
568                        }
569                        return $this->redirect('/maintenance/regular');
570                    }
571                }
572            }
573        }
574        
575        //add link to sp
576        $device = myTools::getDevice();
577        $showLink = ($device == 2 || $device == 3 || $device == 4)? 1: 0;
578        $this->set('showLink', $showLink);
579        
580        // check current controller
581        $currentPageController = isset($this->params['controller']) ? trim(strtolower($this->params['controller'])) : null;
582        $userData = false;
583        
584        // if logged in
585        if ($this->Auth->loggedIn()) {
586            # get user data
587            $this->User->openDBReplica();
588            $this->User->virtualFields['complimentary_code'] = "(SELECT Code.code FROM comp_code_usage AS Code WHERE Code.user_id = User.id AND Code.active_flg = 1 LIMIT 1)";
589            $userData = $this->User->find('first', array(
590                'fields' => [
591                    'User.*',
592                    'UsersExtend.*',
593                    'UsersDetail.*',
594                    'CorporateActivationManagement.*'
595                ],
596                'joins' => [
597                    [
598                        'table' => 'users_extend',
599                        'alias' => 'UsersExtend',
600                        'type' => 'LEFT',
601                        'conditions' => 'UsersExtend.user_id = User.id'
602                    ],
603                    [
604                        'table' => 'corporate_activation_managements',
605                        'alias' => 'CorporateActivationManagement',
606                        'type'    => 'LEFT',
607                        'conditions'    => 'User.id = CorporateActivationManagement.user_id'
608                    ],
609                    [
610                        'table' => 'users_detail',
611                        'alias' => 'UsersDetail',
612                        'type' => 'LEFT',
613                        'conditions' => 'UsersDetail.user_id = User.id'
614                    ]
615                ],
616                'recursive' => -1,
617                'conditions' => array('User.id' => $this->Auth->user('id'))
618            ));
619            $this->User->closeDBReplica();
620
621            $userData['User']['payment_plan_id'] ??= '';
622            $userData['User']['corporate_id'] ??= '';
623            $userData['User']['corporate_individual_payment_flg'] ??= '';
624
625            $this->isWithdrawn = (isset($userData['User']['status']) && $userData['User']['status'] == 9) ? true : false;
626            
627            // redirect to change pass if stasapu tos user and temporary password not change.
628            if (
629                !$this->RequestHandler->isMobile() &&
630                strtolower($this->params->params['action']) != 'changefirstpass' &&
631                strtolower($this->params->params['action']) != 'logout' &&
632                isset($userData['UsersExtend']['temporary_pw_flg']) &&
633                $userData['UsersExtend']['temporary_pw_flg']
634            ) {
635                return $this->redirect('/account/change-first-pass');
636            } elseif(
637                // NJ-23929: redirect to change pass if user is registered through corporate
638                !$this->RequestHandler->isMobile() &&
639                strtolower($this->params->params['action']) != 'changefirstpass' &&
640                strtolower($this->params->params['action']) != 'logout' &&
641                isset($userData['CorporateActivationManagement']['temporary_pw_flg']) &&
642                $userData['CorporateActivationManagement']['temporary_pw_flg'] == 1
643            ){
644                return $this->redirect('/account/change-first-pass');
645            } elseif (
646                $this->RequestHandler->isMobile() &&
647                strtolower($this->params->params['controller']) != 'account' &&
648                strtolower($this->params->params['controller']) != 'index' &&
649                strtolower($this->params->params['action']) != 'logout' &&
650                isset($userData['UsersExtend']['temporary_pw_flg']) &&
651                $userData['UsersExtend']['temporary_pw_flg']
652            ) {
653                return $this->redirect('/account');
654            }
655
656            $userObj = new UserTable($userData['User']);
657            $userObj->currency_code ??= '';
658            if ($this->request->params['controller'] === 'login' &&
659                ($this->request->params['action'] === 'index' || $this->request->params['action'] === 'logout')) {
660                return;
661            }
662
663            if (!$this->RequestHandler->isMobile() && in_array($userObj->corporate_id, Configure::read("blocked_corporate_member_types"))) {
664                $remoteAddress = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : "0.0.0.0";
665
666                if (!in_array($remoteAddress, Configure::read("corporate_allowed_ip"))) {
667
668                    $params = array(
669                        'message' => '特定法人で許可されていないIPアドレスからアクセスがありました。',
670                        'member_id' => $user['id'] ?? '',
671                        'type' => 'IPアドレス:' . $remoteAddress,
672                    );
673
674                    $userObj->slackSoftbankNotice($params);
675
676                    return $this->corporateIpRestrictionLogout();
677                }
678            }
679
680            $this->allowedCoupon = $userObj->allowedMemberCoupon();
681
682            #NC-7922: update username fo studysapuri
683            if (isset($userData['User']['studysapuri_id']) && $userData['User']['studysapuri_id']) {
684                $userData['User']['nickname'] = str_replace("[Study Sapuri ENGLISH] ","", $userData['User']['nickname']);
685            }
686
687            if (
688                isset($userData['User']['card_company']) &&
689                (
690                    $userData['User']['card_company'] == Configure::read('card_company.paypal') ||
691                    isset($userData['User']['paypal_billing_agreement_id'])
692                )
693            ) {
694                $this->isPayPalUser = true;
695            } else if (
696                isset($userData['User']['card_company']) &&
697                (
698                    $userData['User']['card_company'] == Configure::read('card_company.aftee') || 
699                    (empty($userData['User']['card_company']) && $userData['User']['card_brand'] == 'AFTEE' && !empty($userData['User']['aftee_transaction_identifier']))
700                )
701            ) {
702                $this->isAfteeUser = true;
703            } else if (
704                in_array($userData['User']['card_company'], Configure::read('card_company.stripe')) || 
705                (!empty($userData['User']['stripe_customer_id']) && !empty($userData['User']['stripe_payment_identifier']))
706            ) {
707                $this->isStripeUser = true;
708
709                if ($userData['User']['card_company'] == Configure::read('card_company.stripe.apple')) {
710                    $this->isStripeAppleUser = true;
711                } elseif ($userData['User']['card_company'] == Configure::read('card_company.stripe.google')) {
712                    $this->isStripeGoogleUser = true;
713                }                
714            }
715
716            if (!empty($userData['User']['timezone_id'])) {
717                $this->loadModel('Timezone');
718                //get memcached timezone
719                $memcachedTimeDiff = $memcached->get('user-timediff-' . $userData['User']['id']);
720                if (!isset($memcachedTimeDiff['timeDiff']) || !isset($timeDiffData['utc'])) {
721                    $this->Timezone->openDBReplica();
722                    $timezone = $this->Timezone->find('first', array(
723                        'fields' => array('Timezone.continent_id', 'Timezone.city_eng'),
724                        'conditions' => array('Timezone.id' => $userData['User']['timezone_id'])
725                    ));
726                    $this->Timezone->closeDBReplica();
727                    $timeDiffData = array('success' => false);
728                    if ($timezone) {
729                        //get user time difference
730                        $timeDiffData = $this->Timezone->computeTimeDiff(array('continent_id' => $timezone['Timezone']['continent_id'], 'city' => $timezone['Timezone']['city_eng']));
731                    }
732                    if ($timeDiffData['success']) {
733                        $this->timeDiff = $timeDiffData['timeDiff'];
734                        $this->utcOffset = $timeDiffData['utc'];
735                     }
736
737                    //save to memcache
738                    $memcached->set(array(
739                        'key' => 'user-timediff-' . $userData['User']['id'],
740                        'value' => array(
741                            'timeDiff' => $this->timeDiff,
742                            'utc' => $this->utcOffset
743                        ),
744                        'expire' => 604800 //1 week
745                     ));
746                } else {
747                    //get memcached time difference
748                    $this->timeDiff = $memcachedTimeDiff['timeDiff'];
749                    $this->utcOffset = $memcachedTimeDiff['utc'];
750                }
751                //compute time difference in seconds
752                $this->timeDiffSecond = intval($this->timeDiff * 60);
753                //get user time
754                $this->displayTime = $this->Timezone->getUserTime(array('timeDiff' => $this->timeDiff));
755            } else {
756                //use server timezone Asia/Tokyo if timezone is not set
757                $this->displayTime = time();
758            }
759
760            // NC-7360 : Corporate Light Individual Payment
761            $corpType = myTools::getCoporateTypeUsingPaymentPlanId($userData['User']['payment_plan_id'] );
762            $this->clpip = ($userData['User']['corporate_id'] && $corpType == Configure::read("corporate_type.light") && $userData['User']['corporate_individual_payment_flg'] == 1);
763
764            // NC-7922
765            $this->studySapuriId = isset($userData['User']['studysapuri_id']) ? $userData['User']['studysapuri_id'] : NULL;
766            $this->isStudySapuriTosUser = !empty($userData['UsersExtend']['id']) ? true : false;
767            $this->isTemporaryPassword = $userData['UsersExtend']['temporary_pw_flg'] ?? '';
768            $this->defaultCameraSetting = (isset($userData['UsersDetail']['new_camera_flg']) && is_numeric($userData['UsersDetail']['new_camera_flg'])) ? $userData['UsersDetail']['new_camera_flg'] : 1;
769        } else {
770            //use system time if not yet login
771            $this->displayTime = time();
772
773            $apiToken = isset($this->request->query['token']) ? $this->request->query['token'] : null;
774            if (trim($apiToken) != null) {
775                $this->User->openDBReplica();
776                $appUserData = $this->User->find('first', array(
777                    'fields' => array(
778                        'User.id',
779                        'User.currency_code',
780                        'User.studysapuri_id',
781                        'User.corporate_id',
782                        'User.card_company',
783                        'User.paypal_billing_agreement_id',
784                        'UsersExtend.id',
785                        'User.aftee_transaction_identifier',
786                        'User.card_brand',
787                        'User.card_number',
788                        'User.paypal_payer_id',
789                        'User.paypal_payer_email',
790                        'User.stripe_customer_id',
791                        'User.stripe_payment_identifier',
792                        'User.payment_plan_id',
793                        'User.status',
794                    ),
795                    'joins' => [
796                        [
797                            'table' => 'users_extend',
798                            'alias' => 'UsersExtend',
799                            'type' => 'LEFT',
800                            'conditions' => 'UsersExtend.user_id = User.id'
801                        ]
802                    ],
803                    'conditions' => array('User.api_token' => $this->request->query['token']),
804                    'recursive' => -1,
805                ));
806                $this->User->closeDBReplica();
807
808                if ($appUserData) {
809                    // set sapuri id
810                    if (isset($appUserData['User']['studysapuri_id'])) {
811                        $this->studySapuriId = $appUserData['User']['studysapuri_id'];
812                    }
813
814                    if (!empty($appUserData['UsersExtend']['id'])) {
815                        $this->isStudySapuriTosUser = true;
816                    }
817
818                    // set isPayPalUser
819                    if (
820                        (isset($appUserData['User']['card_company']) && $appUserData['User']['card_company'] == Configure::read('card_company.paypal')) ||
821                        isset($appUserData['User']['paypal_billing_agreement_id'])
822                    ) {
823                        $this->isPayPalUser = true;
824                    }
825
826                    // set isAfteeUser
827                    if (
828                        (isset($appUserData['User']['card_company']) && $appUserData['User']['card_company'] == Configure::read('card_company.aftee')) ||
829                        (empty(isset($appUserData['User']['card_company'])) && isset($appUserData['User']['card_brand']) && isset($appUserData['User']['aftee_transaction_identifier']) && $appUserData['User']['card_brand'] == 'AFTEE' && !empty($appUserData['User']['aftee_transaction_identifier']))
830                    ) {
831                        $this->isAfteeUser = true;
832                    }
833
834                    // set isStripeUser 
835                    if (
836                        (isset($appUserData['User']['card_company']) && in_array($appUserData['User']['card_company'], Configure::read('card_company.stripe'))) || 
837                        (empty($appUserData['User']['card_company']) && isset($appUserData['User']['stripe_customer_id']) && isset($appUserData['User']['stripe_payment_identifier']) && !empty($appUserData['User']['stripe_customer_id']) && !empty($appUserData['User']['stripe_payment_identifier']))
838                    ) {
839                        $this->isStripeUser = true;
840                    
841                        if (isset($appUserData['User']['card_company'])) {
842                            if ($appUserData['User']['card_company'] == Configure::read('card_company.stripe.apple')) {
843                                $this->isStripeAppleUser = true;
844                            } elseif ($appUserData['User']['card_company'] == Configure::read('card_company.stripe.google')) {
845                                $this->isStripeGoogleUser = true;
846                            }
847                        }
848                    }
849
850                    $this->isWithdrawn = (isset($appUserData['User']['status']) && $appUserData['User']['status'] == 9) ? true : false;
851
852                    $this->mobAppUserData = $appUserData;
853                }
854            }
855        }
856
857        $this->set('isStripeUser', $this->isStripeUser);
858        $this->set('isStripeAppleUser', $this->isStripeAppleUser);
859        $this->set('isStripeGoogleUser', $this->isStripeGoogleUser);
860        $this->set('isPayPalUser', $this->isPayPalUser);
861        $this->set('isAfteeUser', $this->isAfteeUser);
862        
863        //NC-5125 iso_639_1 for meta tag
864        $this->lang_iso = $this->User->getLangIso($this->request->query);
865        $this->set('lang_iso', $this->lang_iso);
866
867        // header data
868        if (
869            $this->Auth->loggedIn() && 
870            $this->request->params['action'] != "callLessonAlertandStartButton" &&
871            !$this->request->is('ajax') &&
872            (
873                isset($this->params['controller']) && 
874                ($currentPageController != 'class' && $currentPageController != 'htmltextbook' && $currentPageController != 'cs' && !($currentPageController == 'account' && $this->request->params['action'] == 'index'))
875            ) &&
876            !(strpos($this->params->url, 'paypal/create-billing-agreement-token') !== false) &&
877            !(strpos($this->params->url, 'Payment/zeuspayGetChallenge') !== false) &&
878            !(strpos($this->params->url, 'faq') !== false) &&
879            !(strpos($this->params->url, 'entire_faq') !== false)
880        ) {
881            //load redis
882            App::uses('myRedis', 'Lib');
883            $redis = new myRedis();
884            
885            //set key
886            $key = 'ACTIVE_USER_PC_'.$userData['User']['id'];
887
888            //check
889            if (!$redis->get($key)) {
890                $redis->set(array(
891                    'key' => $key,
892                    'value' => 1,
893                    'expire' => 600 //10 minutes adjust to lessons
894                ));
895
896                //load model
897                $this->loadModel('UserMonitoring');
898
899                //update users monitoring
900                $this->UserMonitoring->upsert(array(
901                    'user_id' => $userData['User']['id'],
902                    'device_type' => 1 //pc
903                ));
904            }
905
906            // check user status
907            if (isset($userData['User']) && $userData['User']['status']=='9') {
908                $this->log('[NJ-65075] AppController.php L#'.__LINE__.' -- '.json_encode(array('user_data' => $userData['User'], 'request_data' => $this->request)), 'error');
909                $this->Auth->logout();
910                return $this->redirect(myTools::getUrl());
911            }
912        }
913
914        // load model
915        $this->loadModel('IpBlock');
916        $route = $this->params->url;
917
918        if ($this->IpBlock->blocked() || $this->isWithdrawn) {
919            $urlRedirect = myTools::getUrl();
920            $actionName = isset($this->request->params['action']) ? trim($this->request->params['action']) : null;
921
922            // pc if login
923            if ($this->Auth->loggedIn()) {
924                if (
925                    strtolower($actionName) != 'getalltextbookoption' && // reservation
926                    strtolower($actionName) != 'ajaxchapter' && // reservation
927                    !$this->request->is('ajax') &&
928                    !(strpos($route, 'cs/8') !== false) &&
929                    !(strpos($route, 'cs/confirm') !== false) &&
930                    !(strpos($route, 'cs/complete') !== false) &&
931                    strtolower($currentPageController) != 'htmltextbook' &&
932                    strtolower($currentPageController) != 'faq' &&
933                    !(strpos($route, 'Payment/zeuspayGetChallenge') !== false) &&
934                    !(strpos($route, 'paypal/create-billing-agreement-token') !== false) &&
935                    !($currentPageController == 'account' && $this->request->params['action'] == 'index')
936                ) {
937
938                    $this->loadModel('LessonOnair');
939                    // if has ongoing lesson
940                    $ongoingLesson = $this->LessonOnair->find('count', array(
941                        'conditions' => array(
942                            'status' => 3,
943                            'user_id' => $this->Auth->user('id')
944                        ),
945                        'recursive' => -1
946                    ));
947
948                    if (!$ongoingLesson) {
949                        $this->Cookie->delete('stealth');
950                        $memcached = new myMemcached();
951                        $memcached->delete('user-timediff-' . $this->Auth->user('id')); //delete timezone in memcache
952                        unset($_SESSION['google_login_token']);
953                        $this->Cookie->delete('rememberMe');
954
955                        // set cookie variable to be deleted
956                        $this->Cookie->name = 'searchTeacherForm';
957                        $this->Cookie->domain = $_SERVER['SERVER_NAME'];
958                        $this->Cookie->delete('searchReserveData');
959
960                        if ($this->Session->check('promoteApp')) {
961                            $this->Session->delete('promoteApp');
962                        }
963
964                        // reset timezone check
965                        if (isset($_COOKIE['timezone_dialog_show'])) {
966                            setcookie('timezone_dialog_show', 'on', 1);
967                        }
968
969                        // NC-7459
970                        $this->Session->delete('complimentary_user_disable_links'); // delete
971
972                        $this->loadModel('UsersIpLog');
973                        $this->UsersIpLog->sendSlackNotifToBlockedLoggedInUser(array('userId' => $userData['User']['id']));
974
975                        if (
976                            strtolower($this->request->params['controller']) == 'cs' ||
977                            (strtolower($this->request->params['controller']) == 'localize' && strtolower($actionName) == 'index') ||
978                            (strtolower($this->request->params['controller']) == 'entirefaq' && strtolower($actionName) == 'index')
979                        ) { // faq and cs
980                            if(isset($userData['User']['studysapuri_id'])) {
981                                $urlRedirect .= '/faq/category';
982                            } else {
983                                $urlRedirect .= '/cs/8';
984                            }
985                            return $this->redirect($urlRedirect);
986                        }
987                        $this->log('[NJ-65075] AppController.php L#'.__LINE__.' -- '.json_encode(array('user_data' => $userData['User'], 'request_data' => $this->request)), 'error');
988                        $this->Auth->logout();
989                        return $this->redirect($urlRedirect);
990                    }
991                }
992            // pc non login
993            } elseif ( 
994                !$this->request->is('ajax') &&
995                !empty($route) &&
996                !in_array($route, array('login')) &&
997                !(strpos($route, 'cs/8') !== false) &&
998                !(strpos($route, 'cs/confirm') !== false) &&
999                !(strpos($route, 'mobapp/close') !== false) &&
1000                !(strpos($route, 'cs/complete') !== false) &&
1001                !(strpos($route, 'mobapp/register') !== false) &&
1002                !(strpos($route, 'mobapp/home') !== false) &&
1003                !(strpos($route, 'paypal/create-billing-agreement-token') !== false) &&
1004                !isset($this->request->query['appVersion']) &&
1005                !isset($this->request->query['deviceType']) &&
1006                !isset($this->request->query['token']) &&
1007                strtolower($currentPageController) != 'htmltextbook' &&
1008                strtolower($currentPageController) != 'mobapp' &&
1009                !in_array($route, Configure::read('main_supported_language')) &&
1010                !(strpos($route, 'Payment/zeuspayGetChallenge') !== false)
1011            ) {
1012                if (
1013                        strtolower($this->request->params['controller']) == 'cs' || 
1014                        strtolower($this->request->params['controller']) == 'localize'
1015                    ) { // faq and cs
1016                    $urlRedirect .= '/cs/8'; 
1017                }
1018                return $this->redirect($urlRedirect);
1019            // web view
1020            } elseif (
1021                !$this->request->is('ajax') &&
1022                strtolower($currentPageController) != 'htmltextbook' &&
1023                strtolower($currentPageController) != 'class' &&
1024                (strtolower($currentPageController) == 'mobapp' || ($currentPageController == 'payment' && $actionName == 'mobapp_credit_charge_form')) &&
1025                !(strpos($route, 'mobapp/home') !== false) &&
1026                !(strpos($route, 'mobapp/close') !== false) &&
1027                !in_array($route, array('login')) &&
1028                !(strpos($route, 'paypal/create-billing-agreement-token') !== false) &&
1029                !empty($route) &&
1030                !in_array($route, Configure::read('main_supported_language'))
1031
1032            ) {
1033                if (
1034                    isset($this->request->query['token']) &&
1035                    !(strpos($route, 'mobapp/register') !== false)
1036                ) {
1037                    if ((
1038                            strpos($route, 'mobapp/cs') !== false ||
1039                            strpos($route, 'mobapp/confirm') !== false
1040                        ) &&
1041                        isset($this->request->query['c']) &&
1042                        $this->request->query['c'] == 8
1043                    ) {
1044                        // do nothing
1045                    } else if((
1046                                strpos($route, 'mobapp/cs') !== false ||
1047                                strpos($route, 'mobapp/confirm') !== false ||
1048                                strpos($route, 'mobapp/menu_inquiry') !== false ||
1049                                strpos($route, 'mobapp/faq') !== false
1050                            ) &&
1051                            (empty($this->request->query['c']) || (isset($this->request->query['c']) && $this->request->query['c'] != 8))
1052                    ) {
1053                        $urlRedirect = myTools::getUrl() . '/mobapp/cs' . myTools::getMobappToken($_GET) . '&c=8';
1054                        return $this->redirect($urlRedirect);
1055                    } else {
1056                        $appVersion = isset($this->request->query['appVersion']) && !empty($this->request->query['appVersion']) ? $this->request->query['appVersion'] : 0;
1057                        $deviceType = isset($this->request->query['deviceType']) && !empty($this->request->query['deviceType']) ? $this->request->query['deviceType'] : 0;
1058                        if(!empty($appVersion) && !empty($deviceType)) {
1059                            if (in_array($deviceType, [1,2,3])) {
1060                                $appVersionCompare = version_compare($appVersion, Configure::read('ip_block_app_version')[$deviceType], '<');
1061                                if (!$appVersionCompare) {
1062                                    return $this->redirect('nativecamp://view/is_blocked');
1063                                }
1064                            }
1065                        }
1066                    }
1067                    
1068                } else {
1069                    $urlRedirect = myTools::getUrl() . '/mobapp/home' . myTools::getMobappToken($_GET);
1070                    if (
1071                        strpos($route, 'mobapp/home') !== false ||
1072                        (
1073                            (
1074                                strpos($route, 'mobapp/cs') !== false ||
1075                                strpos($route, 'mobapp/confirm') !== false
1076                            ) &&
1077                            isset($this->request->query['c']) &&
1078                            $this->request->query['c'] == 8
1079                        )
1080                    ) {
1081                        // do nothing
1082                    } else {
1083                        // for mobapp cs blocked ip address
1084                        $route = parse_url($route, PHP_URL_PATH);
1085                        if (
1086                                strpos($route, 'mobapp/cs') !== false || 
1087                                strpos($route, 'mobapp/faq') !== false 
1088                            ) {
1089                            $urlRedirect = myTools::getUrl() . '/mobapp/cs' . myTools::getMobappToken($_GET) . '&c=8';
1090                        }
1091
1092                        return $this->redirect($urlRedirect);
1093                    }
1094                }
1095            }
1096        }
1097
1098        // 4372 textbook name cached
1099        $textbookNamesCached = $memcached->get(Configure::read('textbook_names_cache_key'));
1100
1101        // set shared userData
1102        $this->sharedUserData = $userData;
1103
1104        // set userCurrencyCode
1105
1106        $defaultCurrencyCode = Configure::read('default.user_currency');
1107        $allowedCurrencies = Configure::read('pc_allowed_currencies');
1108        $currencyCode = isset($allowedCurrencies[$this->localizeDir]) ? $allowedCurrencies[$this->localizeDir] : $defaultCurrencyCode;
1109
1110        if(isset($this->mobAppUserData) && $this->mobAppUserData['User']['currency_code']) {
1111            $setCurrencyCode = $this->mobAppUserData['User']['currency_code'];
1112        } else {
1113            $setCurrencyCode = (
1114                isset($this->sharedUserData)
1115                && is_array($this->sharedUserData)
1116                && isset($this->sharedUserData['User'])
1117                && is_array($this->sharedUserData['User'])
1118                && isset($this->sharedUserData['User']['currency_code'])
1119                && $this->sharedUserData['User']['currency_code']
1120            )
1121                ? $this->sharedUserData['User']['currency_code']
1122                : $currencyCode;
1123        }
1124        $this->set('userSetCurrencyCode', $setCurrencyCode);
1125        
1126        myTools::setCurrencyCode($setCurrencyCode);
1127        
1128        // remove success session from registration
1129        $this->Session->delete('registerSuccessEnd');
1130        $this->set('textbookNamesCached', $textbookNamesCached);
1131        $this->set('auth', $this->Auth);
1132        $this->set(compact('userData'));
1133        $this->set('isMobileRequestHandler', $this->RequestHandler->isMobile());
1134        //timezone data
1135        $this->set(array(
1136            'timeDiff' => $this->timeDiff,
1137            'timeDiffSecond' => $this->timeDiffSecond,
1138            'displayTime' => $this->displayTime,
1139            'utcOffset' => $this->utcOffset,
1140            'allowedCoupon' => $this->allowedCoupon ? true : false
1141        ));
1142        
1143        // NC-7459 check complimentary user's status, force redirect to conversion page if expired.
1144        // @TODOs check mobapp and payment, lessons, sp pages.
1145        // callLessonAlertandStartButton
1146        // ($currentPageController != 'class' && $currentPageController != 'htmltextbook')
1147        $excludeControllers = array(
1148            "mobapp", 
1149            "payment", 
1150            "cs", 
1151            "lessonfinish", 
1152            "class", 
1153            "htmltextbook", 
1154            "register"
1155        );
1156        $excludeActions = array(
1157            "continuoususe_advertising", 
1158            "continuoususe_promotion", 
1159            "logout", 
1160            "callLessonAlertandStartButton", 
1161            "credit_form", 
1162            "credit_form_process", 
1163            "credit_form_success", 
1164            "complete", 
1165            "change_to_premium", 
1166            "premium", 
1167            "wp_credit_form", 
1168            "notice_to_user", 
1169            "spcreditform"
1170        );
1171
1172        $this->CompCodeUsage->openDBReplica();
1173        $getUserCompStatus = $this->CompCodeUsage->find('first', array(
1174                'fields' => [
1175                    'CompCodeUsage.code',
1176                    'CompCodeUsage.expire_flg',
1177                    'CompCodeUsage.used_at'
1178                ],
1179                'recursive' => -1,
1180                'conditions' => array('CompCodeUsage.user_id' => $this->Auth->user('id'),
1181                 'CompCodeUsage.active_flg' => 1)
1182            ));
1183        $this->CompCodeUsage->closeDBReplica();
1184
1185        $complimentaryCode = "";
1186        $chargeDate = "";
1187        $compCodeIsExpired = "";
1188        if(!empty($getUserCompStatus)){
1189            $complimentaryCode = $getUserCompStatus['CompCodeUsage']['code'];
1190            $chargeDate = $getUserCompStatus['CompCodeUsage']['used_at'];
1191            $compCodeIsExpired = $getUserCompStatus['CompCodeUsage']['expire_flg'];
1192        }
1193
1194        $userDataForCompStatus = array(
1195            'id' => $this->Auth->user('id'),
1196            'complimentary_code' => $complimentaryCode,
1197            'first_charge_date' => $chargeDate
1198        );
1199        
1200        $currentController = isset($this->request->params['controller']) ? trim(strtolower($this->request->params['controller'])) : null;
1201        $currentAction = isset($this->request->params['action']) ? trim($this->request->params['action']) : null;
1202        $conditions = $this->Auth->loggedIn()
1203        && isset($userData['User'])
1204        && isset($complimentaryCode)
1205        && isset($userData['User']['payment_plan_id'])
1206        && $userData['User']['payment_plan_id'] == Configure::read('payment_plans.complimentary_plan')
1207        && !$this->request->is('ajax')
1208        && !in_array($currentController, $excludeControllers)
1209        && !in_array($currentAction, $excludeActions);
1210
1211        $this->loadModel('ComplimentaryCode');
1212        $comPlanData = $this->ComplimentaryCode->getUserComplimentaryPlanStatus($userDataForCompStatus);
1213        // this code is for redirection to mypage if condition is not satisfied
1214        if (isset($comPlanData['complimentary_plan_conversion_url']) && 
1215            ($comPlanData['complimentary_plan_conversion_url'] === '/continuoususe/advertising' || 
1216            $comPlanData['complimentary_plan_conversion_url'] === '/continuoususe/promotion')) {
1217            $conditions = $conditions && $compCodeIsExpired;
1218        }
1219        
1220
1221        if ($conditions) {
1222            // check
1223            if (
1224                isset($comPlanData['compliemntary_plan_can_lesson'])
1225                && !$comPlanData['compliemntary_plan_can_lesson']
1226                && isset($comPlanData['complimentary_plan_conversion_url'])
1227            ) {
1228                // $comPlanData['complimentary_plan_conversion_url'] = "/continuoususe/promotion";
1229                $complimentaryConversionType = isset($comPlanData['template_type']) ? $comPlanData['template_type'] : 0;
1230                $coin_award = isset($comPlanData['coin_award']) ? $comPlanData['coin_award'] : 0;
1231                $this->Session->write('complimentary_user_disable_links', true);
1232                return $this->redirect(myTools::getUrl() . $comPlanData['complimentary_plan_conversion_url']);
1233            }
1234        }
1235
1236
1237        // parent avatar json data
1238        $avatarJson = null;
1239        $avS3PageCont = array('mypage','waiting','favorite');
1240        $avS3PageActions = array('index');
1241        if ( 
1242            $this->Auth->loggedIn() && 
1243            in_array($currentController, $avS3PageCont) && 
1244            in_array($currentAction, $avS3PageActions)
1245        ) {
1246            $avatarJson = TeacherTable::getAvatarChildJson();
1247        }
1248
1249        // NJ-51
1250        $lessonPriorityControllerArr = Configure::read('priority_lesson_group_data_info.web.controller');
1251        $lessonPriorityActionArr = Configure::read('priority_lesson_group_data_info.web.action');
1252        if ( 
1253            $this->Auth->loggedIn() && 
1254            in_array($currentController, $lessonPriorityControllerArr) && 
1255            in_array($currentAction, $lessonPriorityActionArr)
1256        ) {
1257            $this->studentLessonPriorityTimeDelayInSeconds = $this->User->userPriorityDelay( array( 'user_id' => $this->Auth->user('id') ) );
1258        }
1259
1260        // delete diablelink flag, if navigate to not restricted page.
1261        if (
1262            !in_array($currentAction, $excludeActions)
1263            && !$this->request->is('ajax')
1264        ) {
1265            $this->Session->delete('complimentary_user_disable_links'); // delete
1266        }
1267
1268        // check if there is/are unsave user lesson connection   data.
1269        if (!$this->request->is('ajax')) {
1270            $cookieKey = 'user_lesson_connection_speed_unsave_data';
1271
1272            // - delete cookie if exists
1273            if (isset($_COOKIE[$cookieKey])) {
1274                if ($this->LessonConnectionSpeedDetail->updateConnectionSpeedInfo($cookieKey, 'user')) {
1275                    unset($_COOKIE[$cookieKey]);
1276                    setcookie($cookieKey, null, -1, '/');
1277                }
1278            }
1279        }
1280
1281        $this->isStudySapuriUser = ($this->isStudySapuriTosUser || $this->studySapuriId);
1282        $this->allowedCurrencies = Configure::read('pc_allowed_currencies');
1283        // NC-7922 : Stasapu cs admin domains not allow access
1284        $this->checkStasapuDomain();
1285        // - set current controller and action
1286        $this->set('avatarJson', $avatarJson);
1287        $this->set('current_controller', $currentController);
1288        $this->set('current_action', $currentAction);
1289        $this->set('studySapuriId', $this->studySapuriId);
1290        $this->set('isStudySapuriTosUser', $this->isStudySapuriTosUser);
1291        $this->set('isStudySapuriUser', $this->isStudySapuriUser);
1292        $this->set('studentLessonPriorityTimeDelayInSeconds', $this->studentLessonPriorityTimeDelayInSeconds);
1293        $this->set('isTemporaryPassword', $this->isTemporaryPassword);
1294        $this->set('defaultCameraSetting', $this->defaultCameraSetting);
1295        $this->set('userCDNPath', Configure::read('user.cdn_path_webroot'));
1296                
1297        //NJ-3882
1298        if (isset($userObj) && $userObj) {
1299            $membershipType = $userObj->getMembershipTypeIndex();
1300            $this->userMembershipType = $membershipType;
1301            $this->set('membershipType', $membershipType);
1302        }
1303
1304        //NJ-13670 New Year Part 1 campaign
1305        $newYear1DesignCampaign = false;
1306        $newYear1CampDateArr = Configure::read('campaign_config.new_year_part_1.period');
1307        if (
1308            (
1309                isset($userObj) && $userObj 
1310                && in_array($userObj->getMembershipTypeIndex(), Configure::read('campaign_config.new_year_part_1.design_valid_memberships'))
1311                && time() >= strtotime($newYear1CampDateArr['start']) && time() <= strtotime($newYear1CampDateArr['end'])
1312            )
1313            || (
1314                (!isset($userObj) || !$userObj)
1315                && time() >= strtotime($newYear1CampDateArr['start']) && time() <= strtotime($newYear1CampDateArr['end'])
1316            )
1317        ) {
1318            $newYear1DesignCampaign = true;
1319        }
1320        $this->set('newYear1DesignCampaign', $newYear1DesignCampaign);
1321
1322        //NJ-14237 Amazon Gift campaign
1323        $amazonGiftCampaign = false;
1324        $amazonGiftCampDateArr = Configure::read('campaign_config.amazongift.period');
1325        if (
1326            (
1327                isset($userObj) && $userObj 
1328                && !$this->isStudySapuriUser
1329                && in_array($userObj->getMembershipTypeIndex(), Configure::read('campaign_config.amazongift.valid_memberships'))
1330                && time() >= strtotime($amazonGiftCampDateArr['start']) && time() <= strtotime($amazonGiftCampDateArr['end'])
1331                && $userObj->currency_code == Configure::read('default.user_currency')
1332                && $this->localizeDir == Configure::read('default.user_language')
1333                && !$this->isStudySapuriUser
1334                && $this->action != 'createAccountStudysapuri'
1335            )
1336            || (
1337                (!isset($userObj) || !$userObj)
1338                && time() >= strtotime($amazonGiftCampDateArr['start']) && time() <= strtotime($amazonGiftCampDateArr['end'])
1339                && $this->localizeDir == Configure::read('default.user_language')
1340                && !$this->isStudySapuriUser
1341                && $this->action != 'createAccountStudysapuri'
1342            )
1343        ) {
1344            if($route == '' || strtolower($route) == 'register'){
1345                $amazonGiftCampaign = true;
1346            }
1347        }
1348        $this->set('amazonGiftCampaign', $amazonGiftCampaign);
1349
1350        $googleTagManager = Configure::read('google_tag_manager.default');
1351        if ($firstSegment) {
1352            $globalLanguageAllowed = Configure::read('global_language.allowed_list');
1353
1354            if (in_array($this->localizeDir, $globalLanguageAllowed)) {
1355                $googleTagManager = Configure::read('google_tag_manager.oversies');
1356            } else if (strpos($firstSegment, 'tutors') !== false || strpos($firstSegment, 'recruit') !== false) {
1357                $googleTagManager = Configure::read('google_tag_manager.others');
1358            }
1359        }
1360        $this->set('googleTagManager', $googleTagManager);
1361
1362        if(
1363            (isset($this->request->query['deviceType']) && $this->request->query['deviceType']) &&
1364            (isset($this->request->query['appVersion']) && $this->request->query['appVersion'])) {
1365            $this->NCPlusPositionUrlScheme($this->request->query['appVersion'], $this->request->query['deviceType']);
1366        }
1367        // NJ-37156: Set flag for lite plan users in all pages
1368        $isLitePlanUser = is_array($userData) && in_array($userData['User']['payment_plan_id'], Configure::read('lite_payment_plans')) ? 1 : 0;
1369        $this->set('isLitePlanUser', $isLitePlanUser);
1370
1371        // Study Abroad
1372        $ryugakuAllowedLang = Configure::read('ryugaku_language.allowed_list');
1373        if (in_array($currentController, array('studyabroad', 'studyabroadcreateestimate'))  && !in_array($this->localizeDir, $ryugakuAllowedLang)) {
1374            return $this->redirect('/');
1375        }
1376
1377        //- NJ-27262
1378        //- Redirect chocotto user to download page if logs on PC/SP
1379        if($this->Auth->loggedIn()) {
1380
1381            if (isset($userObj) && $userObj && isset($userObj->payment_plan_id)) {
1382                $isChocottoUser = in_array($userObj->payment_plan_id, [
1383                    Configure::read('payment_plans.free_trial_chocotto'), 
1384                    Configure::read('payment_plans.chocotto_plan')
1385                ]);
1386                
1387                // - check if not accessing study abroad
1388                $notStudyAbroadAccess = (
1389                    (strpos($route, 'study_abroad') === false) 
1390                    && !$this->request->is('ajax') 
1391                    && !in_array($currentController, array('studyabroad', 'studyabroadcreateestimate', 'studyabroadfavorite'))
1392                );
1393
1394                if($isChocottoUser && $notStudyAbroadAccess) {
1395                    $this->log('[NJ-65075] AppController.php L#'.__LINE__.' -- '.json_encode(array('user_data' => $userObj, 'request_data' => $this->request, 'param_data' => $this->params)), 'error');
1396                    $this->Auth->logout();
1397                    $this->redirect('/chocotto_camp_success');
1398                }
1399            }
1400        }
1401        
1402        // Initialize $userCorpId either $appUserData or $userData
1403        $userCorpId = null;
1404        if (isset($appUserData['User']['corporate_id']) && !empty($appUserData['User']['corporate_id'])) {
1405            $userCorpId = $appUserData['User']['corporate_id'];
1406        } elseif (isset($userData['User']['corporate_id']) && !empty($userData['User']['corporate_id'])) {
1407            $userCorpId = $userData['User']['corporate_id'];
1408        }
1409
1410        // Check if the user is corporate, retrieve the payment method if corporate_id exists
1411        if (isset($userCorpId) && !empty($userCorpId)) {
1412            $corpIndPayment = $this->Corporate->getPaymentMethod($userCorpId);
1413            if ($corpIndPayment == 1) {
1414                $this->isIndividualCorp = true;
1415            }
1416        }
1417
1418        // Set the variable to check if the user is an individual corporate
1419        $this->set('isIndividualCorp', $this->isIndividualCorp);
1420
1421        // check if Stripe is Supported
1422        $this->checkStripeSupported($userData);
1423        
1424        $custom_lang_format_flag= false;
1425        if(isset($this->localizeDir) && in_array($this->localizeDir, Configure::read("custom_lang_format_support"))) { 
1426            $custom_lang_format_flag = true;
1427        }
1428        $this->set("custom_lang_format_flag",$custom_lang_format_flag);
1429
1430        $currentLang_iso = $this->Session->read('Config.language_iso_1');
1431        
1432        // NJ-57390 - redirect to register or download app 
1433        if (!$this->request->is('post') && !$this->request->is('ajax') && !isset($this->request->query['appVersion'])) {
1434            if(!in_array($this->name, ['Home', 'Register', 'Login', 'Mobapp', 'MobappInquiry','SpTextbook', 'HtmlTextbook', 'Account']) && in_array($currentLang_iso, ['fr', 'de', 'zh-cn'])) {
1435                $url = myTools::getUrl();
1436
1437                if($this->Auth->loggedIn()) {
1438                    $this->log('[NJ-65075] AppController.php L#'.__LINE__.' -- '.json_encode(array('user_data' => $userData, 'lang_iso' => $currentLang_iso, 'request_data' => $this->request)), 'error');
1439                    $this->Auth->logout();
1440                    return $this->redirect($url . '/' . $currentLang_iso . '?download_app=true');
1441                } else {
1442                    return $this->redirect($url . '/' . $currentLang_iso . '/register');
1443                }
1444            }
1445        }
1446    }
1447    
1448    public function setLocalization() {
1449        $source = $this->Cookie->read('source');
1450        if (empty($source)) {
1451            $source = isset($_GET['source']) ? $_GET['source'] : '';
1452        }
1453
1454        // check if demohtmltextbook view and has lang params
1455        if(
1456            isset($this->request->params['controller']) && 
1457            strtolower($this->request->params['controller']) == 'demohtmltextbook'
1458        ){
1459            if(isset($this->request->query['lang']) && $this->request->query['lang']){
1460                $this->localizeDir = $this->request->query['lang'];
1461            }else{
1462                $this->localizeDir = Configure::read('default.user_language');
1463            }
1464
1465        // - if has localize directory - main override!!
1466        } else if (isset($this->request->data['localizeDir']) && mb_strlen($this->request->data['localizeDir'])) {
1467            $this->localizeDir = $this->request->data['localizeDir'];
1468
1469        // - if AJAX and cookie contains value
1470        } else if (
1471            $this->request->is('ajax') 
1472            && $this->Cookie->check('localizeDir')
1473            && (mb_check_encoding($this->Cookie->read('localizeDir'), 'UTF-8')  && strpos($this->Cookie->read('localizeDir'), '�') == false)
1474        ) {
1475            $this->localizeDir = $this->Cookie->read('localizeDir');
1476            
1477            
1478        // - else
1479        } else {
1480            // - if has language parameter
1481            if (
1482                ($this->request && isset($this->request->language) && $this->request->language != Configure::read('default.user_language')) || 
1483                ($this->localizeDir != Configure::read('default.user_language'))
1484            ) {
1485                $this->localizeDir = $this->request->language;
1486
1487            // - whitelisted actions
1488            } else if (
1489                // - if has valid action
1490                isset($this->request->params['action']) && $this->Cookie->check('localizeDir') 
1491
1492                // - valid format
1493                && (mb_check_encoding($this->Cookie->read('localizeDir'), 'UTF-8') && strpos($this->Cookie->read('localizeDir'), '�') == false)
1494                
1495                // - if not home
1496                && !($this->request->params['action'] == "index" && $this->request->params['controller'] == "home")
1497                && !($this->request->params['action'] == "price_mobapp" && $this->request->params['controller'] == "Usage")
1498                && !($this->request->params['action'] == "features" && $this->request->params['controller'] == "mobapp")
1499                && !($this->request->params['action'] == "service_mobapp" && $this->request->params['controller'] == "Usage")
1500                && !($this->request->params['action'] == "menu_inquiry" && $this->request->params['controller'] == "Mobapp")
1501                && !($this->request->params['action'] == "favorite_teachers" && $this->request->params['controller'] == "Mobapp")
1502                && $source != 'okpanda'
1503            ) {
1504                $this->localizeDir = $this->Cookie->read('localizeDir');
1505
1506            // - if has language "la" in query
1507            } else if (
1508                isset($this->request->query['la']) && $this->request->query['la'] != Configure::read('default.user_language')
1509                
1510                // - if home
1511                && (
1512                    ($this->request->params['action'] == "index" && $this->request->params['controller'] == "home") ||
1513                    (isset($this->request->params['overrideLocalizeDir']) && $this->request->params['overrideLocalizeDir']) ||
1514                    ($this->request->params['action'] == "price_mobapp" && $this->request->params['controller'] == "Usage") ||
1515                    ($this->request->params['action'] == "features" && $this->request->params['controller'] == "mobapp") ||
1516                    ($this->request->params['action'] == "service_mobapp" && $this->request->params['controller'] == "Usage") ||
1517                    ($this->request->params['action'] == "menu_inquiry" && $this->request->params['controller'] == "Mobapp") ||
1518                    $source == 'okpanda' ||
1519                    (isset($this->request->params['overrideLocalizeDir']) && $this->request->params['overrideLocalizeDir'])
1520                )
1521            ) {
1522                $this->localizeDir = $this->request->query['la'];
1523            }
1524        }
1525
1526        // get allowed languages
1527        $allowedLanguages = array_flip(Configure::read('pc_allowed_currencies'));
1528
1529        // get currency code
1530        $this->loadModel('GeoIPCountryCurrency');
1531        $currencyCode = $this->GeoIPCountryCurrency->getCurrencyCode();
1532        $this->localizeIPLang = $currencyCode;
1533
1534        $eurAllowedLanguageCodes = array_keys(Configure::read('pc_allowed_currencies'), 'EUR'); // ['fr', 'de'] for now at NJ-57390
1535        $countryCode = $this->GeoIPCountryCurrency->getCountryCode();
1536
1537        if (!empty($this->params->params['language']) && $this->params->params['language'] == 'zh-cn') {
1538            $ipLanguage = $this->params->params['language'];
1539        } else if(in_array(strtolower($countryCode), $eurAllowedLanguageCodes)) {
1540            $ipLanguage = strtolower($countryCode);
1541        } else {
1542            $ipLanguage = !empty($currencyCode) && $currencyCode != 'USD' && isset($allowedLanguages[$currencyCode]) ? $allowedLanguages[$currencyCode] : Configure::read('default.user_language');
1543        }
1544
1545        $controller = $this->params->params['controller'];
1546        $action = $this->params->params['action'];
1547        $route = $this->params->url;
1548        $ipRestrictionFlg = true;
1549
1550        // if vietnam language
1551        if ($ipLanguage == 'vi') {
1552            // check if vnStealth is set
1553            if (isset($this->request->query['vnStealth'])) {
1554                if ($this->request->query['vnStealth'] == 'off') {
1555                    $this->Cookie->delete('excludeIpRestriction');
1556                } elseif ($this->request->query['vnStealth'] == 'on') {
1557                    $this->Cookie->write('excludeIpRestriction', true);
1558                }
1559            }
1560        } else {
1561            $this->Cookie->delete('excludeIpRestriction');
1562        }
1563
1564        if ($this->Cookie->read('excludeIpRestriction')) {
1565            $ipRestrictionFlg = false;
1566        }
1567
1568        // restriction for france and germany, this will not redirect to /de or /fr if ip is germany or france
1569        if (in_array($ipLanguage, ['fr', 'de'])) {
1570            $ipRestrictionFlg = false;
1571        }
1572
1573        // change language based on ip lang if
1574        // if ip language is ko or zh-tw and request language is not equals to ip language
1575        if (
1576            !$this->request->is('post') &&
1577            !$this->request->is('ajax') &&
1578            !isset($this->request->query['la']) &&
1579            in_array($ipLanguage, Configure::read('global_language.allowed_list')) &&
1580            !in_array($action, array('sendDLlink', 'zeuspay', 'corporateZeuspay', 'getWPPaymentResult', 'getAfteePaymentResult', 'stripepay', 'stripepay_manual')) &&
1581            $controller != 'Api' &&
1582            strtolower($controller) != 'mobapp' &&
1583            !(strpos($route, 'mobapp/') !== false) &&
1584            !(strpos($route, 'HtmlTextbook/') !== false) && // for pc textbook
1585            !(strpos($route, 'sp/textbook/') !== false) && // for app textbook
1586            !(strpos($route, 'textbook/getSpeech/') !== false) && // for audio
1587            $ipRestrictionFlg
1588            || // if url was sent from sns sharing
1589            (
1590                isset($_GET["nc_share_ref"]) &&
1591                $_GET["nc_share_ref"] == "nc_sns_share" &&
1592                !(
1593                    (strpos($_SERVER["HTTP_USER_AGENT"], 'facebookexternalhit') !== false) ||
1594                    (strpos($_SERVER["HTTP_USER_AGENT"], 'Twitterbot') !== false) ||
1595                    (strpos($_SERVER["HTTP_USER_AGENT"], 'line-poker') !== false)
1596                )
1597            )
1598            && $source != 'okpanda'
1599        ) {
1600            $isPaymentUrl =  (strpos($route, 'payment/mobapp_') !== false);
1601            if (!empty($this->request->language) && $this->request->language != $ipLanguage && !$isPaymentUrl) {
1602                return $this->redirectUsingIpLang($ipLanguage);
1603            } else {
1604                if (
1605                    $this->checkControllerActionExist($controller, $action) &&
1606                    $this->request->language != $ipLanguage &&
1607                    !$isPaymentUrl
1608                ) {
1609                    return $this->redirectUsingIpLang($ipLanguage);
1610                }
1611            }
1612        }
1613
1614        //NJ-32821
1615        $referringURL = @$_SERVER['HTTP_REFERER'];
1616        // Check if came from zh-tw blog
1617        if (!empty($referringURL)) {
1618            $pattern = '/\/([^\/]+)\/blog\//';
1619            if (preg_match($pattern, $referringURL, $matches) && count($matches) > 1) {
1620                   $zh_tw = $matches[1];
1621                   if(!empty($zh_tw) && $zh_tw == "zh-tw") {
1622                       $this->localizeDir = $zh_tw;
1623                    //$this->log("Redirect : " . $url , "debug");
1624                   }
1625            } 
1626        } 
1627        
1628        // - set cookie information
1629        $this->Cookie->write('localizeDir', $this->localizeDir);
1630        Configure::write('default.localization', $this->localizeDir);
1631        $this->set('localizeDir', $this->localizeDir);
1632
1633        // - if has default language
1634        if ( $this->localizeDir != Configure::read('default.user_language') ) {
1635            if (
1636                // - if not supported
1637                (
1638                    !in_array($this->localizeDir, Configure::read('global_language.allowed_list')) 
1639                    && $this->request->params['controller'] != 'home'
1640                )
1641
1642                // - and not static page
1643                && (
1644                    $this->request->params['controller'] != 'static' 
1645                    && $this->request->params['action'] != 'privacy' 
1646                    && $this->request->params['action'] != 'privacy'
1647                )
1648
1649                // - and not api controller
1650                && (
1651                    $this->request->params['controller'] != 'Api' 
1652                    && $this->request->params['action'] != 'sendDLlink'
1653                )
1654
1655                // - if not mobapp link
1656                && (
1657                    strtolower($this->request->params['controller']) != 'mobapp' 
1658                )
1659
1660                // - if not mobapp link
1661                && (
1662                    strtolower($this->request->params['controller']) != 'payment' 
1663                    && $this->request->params['action'] != 'getHostedPage'
1664                )
1665
1666                // - if not cs page
1667                && (
1668                    strtolower($this->request->params['controller']) != 'cs' 
1669                )
1670
1671                // - if not reregister
1672                && (
1673                    strtolower($this->request->params['controller']) != 'reregister' 
1674                )
1675                
1676                // - if not textbook
1677                && (
1678                    strtolower($this->request->params['controller']) != 'htmltextbook' 
1679                )
1680
1681                
1682                // NJ-11650 - if not FAQ
1683                && (
1684                    strtolower($this->request->params['controller']) != 'entirefaq' 
1685                )
1686                // - if not textbook
1687                && (
1688                    strtolower($this->request->params['controller']) != 'demohtmltextbook' 
1689                )
1690
1691                // - if login + register from Okpanda
1692                && $source != 'okpanda'
1693
1694            ) {
1695                if ($this->Auth->loggedIn()) {
1696                    $this->log('[NJ-65075] AppController.php L#'.__LINE__.' -- '.json_encode(array('localizeDir' => $this->localizeDir, 'request_data' => $this->request)), 'error');
1697                    return $this->redirect($this->Auth->logout());
1698                }
1699                return $this->redirect('/');
1700            }
1701
1702            $this->baseUrl =  myTools::getUrl() . '/' . Configure::read('default.localization');
1703            $this->set('noIndexFlg', true);
1704            
1705            $lang_iso_1 = $this->localizeDir;
1706            $lang_iso_1 = $lang_iso_1 == 'cz' ? 'cs' : $lang_iso_1;
1707            $language_code = $this->CountryCode->convertLangIso(array(
1708                'language_code' => $lang_iso_1,
1709                'target_iso' => 2
1710            ));
1711            $this->Session->write('Config.language', $language_code);
1712            $this->Session->write('Config.language_iso_1', $lang_iso_1);
1713            $this->set('html_lang_iso_1', $lang_iso_1);
1714        } else {
1715
1716            $this->baseUrl =  myTools::getUrl();
1717            $this->set('html_lang_iso_1', $this->localizeDir);    
1718        }
1719
1720        // - apply translation for error message
1721        $this->Auth->authError = __d("login", "再度ログインしなおしてください。");
1722        $this->Auth->loginError = __d("login", "メールアドレス、またはパスワードに誤りがあります。");
1723    }
1724
1725    /**
1726     * redirect with language based on ip address
1727     * @param string  $ipLanguage
1728     * @return string new rurl
1729     */
1730    private function redirectUsingIpLang($ipLanguage) {
1731        $webUrl = $_SERVER['REQUEST_URI'];
1732        $segment = explode('/', $webUrl);
1733
1734        $isSNSShare = false;
1735        // if url has nc_share_ref or shared to SNS 
1736        // parse url to remove query for sns share "nc_share_ref"
1737        if(isset($_GET["nc_share_ref"]) && $_GET["nc_share_ref"]== "nc_sns_share" ){
1738            $parsedUrl = parse_url($webUrl);
1739            parse_str( $parsedUrl['query'], $parameters ); 
1740            unset( $parameters['nc_share_ref'] ); 
1741            $newQuery = http_build_query($parameters);
1742            $isSNSShare = true;
1743        }
1744        
1745
1746        if (!isset($this->request->language)) {
1747            $segment[0] = '/' . $ipLanguage;
1748            $newUrl = implode('/', $segment);
1749            // apply new url if SNS share
1750            if($isSNSShare){
1751                $newUrl = '/' . $ipLanguage . $parsedUrl['path'] .'?'. $newQuery;
1752            }
1753        } else {
1754            $segment[1] = str_replace($segment[1], $ipLanguage, $segment[1]);
1755            $newUrl = implode('/', $segment);
1756            // apply new url if SNS share
1757            if($isSNSShare){
1758                $newParsedUrl = rtrim(str_replace('/'.$this->request->language, '', $parsedUrl['path']), '/');
1759                $newUrl = '/' .  str_replace($segment[1], $ipLanguage, $segment[1]) . $newParsedUrl .'?'. $newQuery;
1760            }
1761        }
1762
1763        return parent::redirect(myTools::getUrl() . $newUrl, null, false);
1764    }
1765
1766    public function redirect($url, $status = null, $exit = true) {
1767        //override redirect to login page with status 301
1768        if (($url == '/login' || $url == myTools::getUrl() . '/user/login') && strtolower($this->request->params['controller']) != 'login') {
1769            $this->response->disableCache();
1770            $url = myTools::getUrl() . '/user/login';
1771            $status = 301;
1772        }
1773
1774        // - if contains mobapp, do not do any processing
1775        if (is_string($url) && strpos($url, "/mobapp") !== false) {
1776            return parent::redirect($url, $status, $exit);
1777        }
1778        
1779        # redirect to Localized URL
1780        if (
1781            $this->localizeDir != 'ja' &&
1782            ((!is_array($url) && $this->localizeDir && strpos($url, "/" . $this->localizeDir) === false) ||
1783            (is_array($url) && $this->localizeDir && !isset($url['language'])))
1784        ) {
1785
1786            if (is_array($url)) {
1787                $url['language'] = $this->localizeDir;
1788            } else {
1789                $parseDomain = false;
1790                #if not nativecamp site avoid editing url
1791                if (strpos($url, 'http://') === 0 || strpos($url, 'https://') === 0) {                    
1792                    $parseUrl = parse_url($url);
1793
1794                    if ($parseUrl['host'] != $_SERVER['HTTP_HOST']) {
1795                        return parent::redirect($url, $status, $exit);
1796                    } else {
1797                        $parseDomain = true;
1798                    }
1799                }
1800                #if not nativecamp not https
1801                if (strpos($url, 'http:') !== false && $parseDomain) {
1802                    $url = str_replace('http:', 'https:', $url);
1803                }
1804                
1805                $baseUrl = myTools::getUrl();
1806                $userDir = "/user";
1807
1808                if (strpos($url, $baseUrl) !== false && strpos($url, $userDir) !== false) {
1809                    $replace = $baseUrl . $userDir;
1810                    $replaceWith = $baseUrl . "/" . $this->localizeDir;
1811                    $url = str_replace($replace, $replaceWith, $url);
1812                } elseif (strpos($url, $baseUrl) !== false) {
1813                    $replace = $baseUrl;
1814                    $replaceWith = $baseUrl . "/" . $this->localizeDir;
1815                    $url = str_replace($replace, $replaceWith, $url);
1816                } else {
1817                    $url = $baseUrl . '/' . $this->localizeDir . $url;
1818                }
1819            }
1820        }
1821
1822        if ($this->localizeDir == 'ja') {
1823            if (is_array($url)) {
1824                unset($url['language']);
1825            } else {
1826                $checkBaseUrl = myTools::getUrl() . '/ja';
1827                
1828                if (strpos($url, $checkBaseUrl) !== false) {
1829                    $replaceWith = myTools::getUrl();
1830                    $url = str_replace($checkBaseUrl, $replaceWith, $url);
1831                } elseif (strpos($url, '/ja/') === 0) {
1832                    $url = str_replace('/ja', '', $url);
1833                }
1834            }
1835        } 
1836
1837        return parent::redirect($url, $status, false);
1838    }
1839
1840    /**
1841    * set Config.language using parameter or browser language
1842    */
1843    public function setConfigLanguage() {
1844        $lang_iso_1 = $language_code = NULL;
1845        $baseUrl = myTools::getUrl();
1846        $localizeNonLpPages = array('tos', 'privacy'); // non LP pages
1847
1848        if ($this->Auth->loggedIn()) {
1849            # get user data
1850            $user = $this->sharedUserData;
1851            $lang_iso_1 = $user['User']['native_language2'] ? $user['User']['native_language2'] : '';
1852        } else {
1853
1854            $path = $this->parseUrl['path'];
1855            $globalLang = Configure::read('global_language.list');
1856
1857            if ($path != '/') {
1858                $segment = explode('/', $path);
1859                $firstSegment = isset($segment[1])? $segment[1]:'';
1860
1861                // redirect to main url
1862                if ($firstSegment == 'ja') {
1863                    $this->log("Redirect : " . __METHOD__ . " (line " . __LINE__ . ") firstSegment = ja, " . $baseUrl , "debug");
1864                    return $this->redirect($baseUrl);
1865                }
1866
1867                // set lang iso_639_1
1868                $lang_iso_1 = $firstSegment == 'cz' ? 'cs' : (strpos($globalLang, $firstSegment) !== false ? $firstSegment : Configure::read('original.default.iso_639_1'));
1869            }
1870        }
1871
1872        if (!empty($lang_iso_1)) {
1873            //return iso_639_2 if supported language
1874            $language_code = $this->CountryCode->convertLangIso(array(
1875                'language_code' => $lang_iso_1,
1876                'target_iso' => 2
1877            ));
1878        } else {
1879            // set default
1880            $language_code = Configure::read('original.default.iso_639_2');
1881            $lang_iso_1 = Configure::read('original.default.iso_639_1');
1882        }
1883
1884        //set sessions
1885        $this->Session->write('Config.language', $language_code);
1886        $this->Session->write('Config.language_iso_1', $lang_iso_1);
1887        setcookie('lang', $lang_iso_1, 0, '/');
1888
1889        # set layoutLang_iso for url in view files
1890        $this->set('layoutLang_iso', "/".($lang_iso_1 == 'cs' ? 'cz' : $lang_iso_1));
1891
1892        // html lang
1893        $this->set('html_lang_iso_1', $lang_iso_1);
1894    }
1895
1896    // This will redirect to restriction page if currency not JPY
1897    // return $userdata = user info.
1898    public function jpyOnlyPage($user = '') {
1899        if (!empty($user)) {
1900            $userData = $user;
1901        } elseif (!empty($this->request->query['token'])) {
1902            $token = $this->request->query['token'];
1903            $userData = $this->User->findByApiToken($token);
1904        } else {
1905            return $this->redirect('/mobapp/retrypage');
1906        }
1907
1908        if (isset($userData['User'])) {
1909            $currencyCode = $userData['User']['currency_code'];
1910            $nativeLanguage = isset($userData['User']['native_language2']) ? $userData['User']['native_language2'] : Configure::read('default.user_language');
1911            // null null currency_code in DB is equal to JPY currency as default
1912            if ($currencyCode == '' || $currencyCode == Configure::read('currency_jpy')) {
1913                return $userData;
1914            } else {
1915                $languageCodeIso2 = $this->CountryCode->convertLangIso(array(
1916                    'language_code' => $nativeLanguage,
1917                    'target_iso' => 2
1918                ));
1919
1920                $confLanguage = $this->CountryCode->checkGlobalLanguage(array(
1921                    'language_code' => $nativeLanguage,
1922                    'unset_language_code' => array('ja')
1923                ));
1924
1925                $controller = strtolower($this->params->params['controller']);
1926
1927                if(
1928                    in_array($controller, array('family')) &&
1929                    in_array($currencyCode, Configure::read('family_plan.allowed_currencies')) &&                     
1930                    in_array($nativeLanguage, Configure::read('family_plan.allowed_languages'))
1931                ){
1932                    $confLanguage = $this->CountryCode->checkGlobalLanguage(array(
1933                        'language_code' => $nativeLanguage
1934                    ));
1935                }
1936                
1937                // set the language for translation
1938                if ($confLanguage) {
1939                    $this->Session->write('Config.language', $languageCodeIso2);
1940                } else {
1941                    $this->Session->write('Config.language', 'eng');
1942                }
1943
1944                
1945                // allow access for family plan pages for other languages
1946                if(
1947                    !in_array($controller, array('family')) &&
1948                    !in_array($currencyCode, Configure::read('family_plan.allowed_currencies'))
1949                ){
1950                    return $this->redirect(myTools::getUrl() . '/mobapp/region_restriction');
1951                }
1952            }
1953        } else {
1954            return $this->redirect('/mobapp/retrypage');
1955        }
1956    }
1957
1958    /* this will redirect to restriction page if language and currency not allowed
1959    * check language for non login user 
1960    */
1961    public function checkIfAllowed() {
1962        // disable foreign language if "la" is set
1963       if (isset($this->request->query['la'])) {
1964            $lang = $this->request->query['la'];
1965            if (!empty($lang) && $lang !== Configure::read('default.user_language')) {
1966                //set language
1967                $languageCodeIso2 = $this->CountryCode->convertLangIso(array(
1968                    'language_code' => $lang,
1969                    'target_iso' => 2
1970                ));
1971
1972                $confLanguage = $this->CountryCode->checkGlobalLanguage(array(
1973                    'language_code' => $lang,
1974                    'unset_language_code' => array('ja')
1975                ));
1976
1977                // set the language for translation
1978                if ($confLanguage) {
1979                    $this->Session->write('Config.language', $languageCodeIso2);
1980                } else {
1981                    $this->Session->write('Config.language', 'eng');
1982                }        
1983                return $this->redirect(myTools::getUrl() . '/mobapp/region_restriction');
1984            }
1985        }
1986        // if token is set check user currency
1987        if (isset($this->request->query['token'])) {
1988            $this->jpyOnlyPage();
1989        }
1990    }
1991
1992    /**
1993    * Set memcache timezone
1994    * @param int userId
1995    * @return array ['timezone_id']
1996    */
1997    public function getTimezoneData($userId = NULL) {
1998        $this->loadModel('Timezone');
1999        //initialize memcache
2000        $memcached = new myMemcached();
2001
2002        $timezone = array(
2003            'Timezone' => array(
2004                'id' => Configure::read('default.user_timezone_id'),
2005            )
2006        );
2007
2008        $defaultTimezoneName = Configure::read('default.timezone_name');
2009
2010        $timezoneName = empty($this->request->data['User']['timezone']) ? $defaultTimezoneName : $this->request->data['User']['timezone'];
2011        $tznArr = explode('/', $timezoneName);
2012
2013        //get continents
2014        $continents = array_flip(Configure::read('continents'));
2015
2016        // log and use user current timezone settings if user computer timezone format is incorrect
2017        if (
2018            !isset($tznArr[0]) ||
2019            (isset($tznArr[0]) && !isset($continents[$tznArr[0]]))
2020        ) {
2021            $this->log(__METHOD__ . ' Timezone value format is incorrect. -->' . json_encode($timezoneName) . ' | userId --> ' . json_encode($userId), 'debug');
2022            $userTimezone = NULL;
2023            if ($userId) {
2024                // get user current timezone used
2025                $userTimezone = $this->User->useReplica()->find('first', array(
2026                    'fields' => 'timezone_id',
2027                    'conditions' => array(
2028                        'id' => $userId,
2029                        'timezone_id is not null' 
2030                    ),
2031                    'recursive' => -1
2032                ));
2033            }
2034
2035            $timezoneName = $defaultTimezoneName;
2036            //Configure::read('default.user_timezone_id');
2037
2038            if ($userTimezone) {
2039                $timezoneList = $this->Timezone->getFormattedTimezones();
2040                $usertimezoneDetail = isset($timezoneList[$userTimezone['User']['timezone_id']]) ? $timezoneList[$userTimezone['User']['timezone_id']] : null;
2041
2042                if ($usertimezoneDetail) {
2043                    $timezone['Timezone']['id'] = $userTimezone['User']['timezone_id'];
2044                } else {
2045                    $this->log(__METHOD__ . ' Timezone is not exist in memcached timezone list. -->' . json_encode($userTimezone) . ' | userId --> ' . json_encode($userId), 'debug');
2046                }
2047            }
2048        } else {
2049            $timezone = $this->Timezone->updateTimezoneTable(array('timezoneName' => $timezoneName));
2050        }
2051
2052        if ($timezone) {
2053            $jpTimeDiffData = $this->Timezone->computeTimeDiff(array(
2054                'continent_id' => isset($timezone['Timezone']['continent_id']) ? $timezone['Timezone']['continent_id'] : NULL,
2055                'city' => isset($timezone['Timezone']['city_eng']) ? $timezone['Timezone']['city_eng'] : NULL
2056            ));
2057
2058            if (isset($jpTimeDiffData['success']) && $jpTimeDiffData['success']) {
2059                $this->timeDiff = $jpTimeDiffData['timeDiff'];
2060                $this->utcOffset = $jpTimeDiffData['utc'];
2061            
2062                //save to memcache 
2063                $memcached->set(array(
2064                    'key' => 'user-timediff-' . $userId,
2065                    'value' => array(
2066                        'timeDiff' => $this->timeDiff,
2067                        'utc' => $this->utcOffset
2068                    ),
2069                    'expire' => 604800 //1 week
2070                ));
2071            }
2072
2073            return array(
2074                'timezone_id' => !empty($timezone['Timezone']['id']) ? $timezone['Timezone']['id'] : NULL
2075            );
2076        }
2077
2078        return NULL;
2079    }
2080
2081    /**
2082    * Settle paypal payment receivables
2083    * @param array user data
2084    * @return boolean
2085    */
2086    protected function chargePayPalPaymentReceivable($params = array()) {
2087        //validate need data for payment receivable
2088        if (
2089            empty($params['id']) ||
2090            empty($params['email']) ||
2091            empty($params['currency_code']) ||
2092            empty($params['payment_plan_id']) ||
2093            empty($params['price_id']) ||
2094            empty($params['card_company']) ||
2095            empty($params['paypal_billing_agreement_id'])
2096        )
2097        {
2098            $this->log(__METHOD__ . "error data pass. Data : " . json_encode($params), 'debug');
2099            return false;
2100        }
2101
2102        $userId = $params['id'];
2103        $currencyCode = $params['currency_code'];
2104        $paymentPlanId = $params['payment_plan_id'];
2105        $priceId = $params['price_id'];
2106
2107        // set db connection
2108        $db = ConnectionManager::getDataSource('default');
2109        //db resources reconnect
2110        if ($db->isConnected()) {
2111            $db->close(); // stop
2112        }
2113        $db->reconnect();
2114
2115        $rawQuery = "SELECT 
2116                (SELECT 
2117                        SUM(`amount`) AS `amount`
2118                    FROM
2119                        `payment_receivables`
2120                    WHERE
2121                        `payment_receivables`.`user_id` = u.id
2122                            AND `payment_receivables`.`status` = 0
2123                            AND `payment_receivables`.`payment_element_type` = 1
2124                            AND `payment_receivables`.`created` <= NOW()) AS receivables,
2125                (SELECT 
2126                        SUM(`amount`) AS `amount`
2127                    FROM
2128                        `payment_receivables`
2129                    WHERE
2130                        `payment_receivables`.`user_id` = u.id
2131                            AND `payment_receivables`.`status` = 0
2132                            AND `payment_receivables`.`payment_element_type` = 2
2133                            AND `payment_receivables`.`created` <= NOW()) AS appreciation_receivables,
2134                (SELECT 
2135                        SUM(`amount`) AS `amount`
2136                    FROM
2137                        `payment_receivables`
2138                    WHERE
2139                        `payment_receivables`.`user_id` = u.id
2140                            AND `payment_receivables`.`status` = 0
2141                            AND `payment_receivables`.`payment_element_type` = 3
2142                            AND `payment_receivables`.`created` <= NOW()) AS live_receivables                        
2143            FROM  users AS u WHERE u.id = {$userId}
2144        ";
2145
2146        $result = $this->User->query($rawQuery);
2147
2148        $receivableAmount = isset( $result[0][0]['receivables'] ) && $result[0][0]['receivables'] ? $result[0][0]['receivables'] : 0 ;
2149        $appreciationReceivableAmount = isset( $result[0][0]['appreciation_receivables'] ) && $result[0][0]['appreciation_receivables'] ? $result[0][0]['appreciation_receivables'] : 0 ;
2150        $liveReceivableAmount = isset( $result[0][0]['live_receivables'] ) && $result[0][0]['live_receivables'] ? $result[0][0]['live_receivables'] : 0 ;
2151        $totalReceivableAmount = $receivableAmount + $appreciationReceivableAmount + $liveReceivableAmount;
2152
2153        // check payment receivable
2154        if ( $totalReceivableAmount < 1 ) {
2155            $this->log(__METHOD__ . "::No payment receivable. \n Data : " . json_encode($params), 'debug');
2156            return false;
2157        }
2158
2159        //generate ordd code
2160        $paymentHash = myTools::generateOrderCode($userId);
2161        $membershipStatusIndex = UserTable::getStudentMembershipStatus($userId);
2162        // Reservation payment transaction 
2163        if( $receivableAmount > 0 ) {
2164
2165            $paymentParams = array(
2166                'currencyCode' => $currencyCode,
2167                'formType' => Configure::read('payment_credit_receivable'),
2168                'paymentType' => Configure::read('payment_types.payment_receivable'),
2169                'logFileName' => 'debug',
2170                'paymentAmount' => $receivableAmount,
2171                'priceId' => $priceId,
2172                'paymentPlanId' => $paymentPlanId
2173            );
2174
2175            $ptParams = array(
2176                'user_id' => $userId,
2177                'payment_hash' => $paymentHash,
2178                'course_id' => Configure::read("credit.course_id"),
2179                'payment_params' => json_encode($paymentParams),
2180            );
2181
2182            // create payment transaction
2183            if (!$pt = $this->PaymentTransaction->setWPPaymentTransaction($ptParams)) {
2184                $this->log(__METHOD__ . "::Cannot create payment transaction. \nData:" .json_encode($ptParams), 'debug');
2185                return false;
2186            }
2187            
2188        }
2189        // Appreciation payment transaction
2190        if( $appreciationReceivableAmount > 0 ) {
2191
2192            $paymentParams = array(
2193                'currencyCode' => $currencyCode,
2194                'formType' => Configure::read('payment_credit_appreciation_receivable'),
2195                'paymentType' => Configure::read('payment_types.payment_receivable'),
2196                'logFileName' => 'debug',
2197                'paymentAmount' => $appreciationReceivableAmount,
2198                'priceId' => $priceId,
2199                'paymentPlanId' => $paymentPlanId
2200            );
2201
2202            $ptParams = array(
2203                'user_id' => $userId,
2204                'payment_hash' => $paymentHash,
2205                'course_id' => Configure::read("credit.course_id"),
2206                'payment_params' => json_encode($paymentParams),
2207            );
2208
2209            // create payment transaction
2210            if (!$apt = $this->PaymentTransaction->setWPPaymentTransaction($ptParams)) {
2211                $this->log(__METHOD__ . "::Cannot create payment transaction. \nData:" .json_encode($ptParams), 'debug');
2212                return false;
2213            }
2214
2215        }
2216
2217        // Live payment transaction
2218        if ($liveReceivableAmount > 0) {
2219
2220            $paymentParams = array(
2221                'currencyCode' => $currencyCode,
2222                'formType' => Configure::read('payment_live_lesson_receivable'),
2223                'paymentType' => Configure::read('payment_types.payment_receivable'),
2224                'logFileName' => 'debug',
2225                'paymentAmount' => $liveReceivableAmount,
2226                'priceId' => $priceId,
2227                'paymentPlanId' => $paymentPlanId
2228            );
2229
2230            $ptParams = array(
2231                'user_id' => $userId,
2232                'payment_hash' => $paymentHash,
2233                'course_id' => Configure::read("credit.course_id"),
2234                'payment_params' => json_encode($paymentParams),
2235            );
2236
2237            // create payment transaction
2238            if (!$lpt = $this->PaymentTransaction->setWPPaymentTransaction($ptParams)) {
2239                $this->log(__METHOD__ . "::Cannot create payment transaction. \nData:" .json_encode($ptParams), 'debug');
2240                return false;
2241            }
2242        }
2243
2244        //db resources reconnect
2245        if ($db->isConnected()) {
2246            $db->close(); // stop
2247        }
2248        $db->reconnect();
2249
2250        // load PayPal class
2251        if (!class_exists('PayPal')) {
2252            App::import('Lib', 'PayPal');
2253        }
2254
2255        $paypal = new PayPal();
2256
2257        // get access token data
2258        $accessTokenData = $paypal->getAccessToken();
2259
2260        // return if error
2261        if (isset($accessTokenData['error'])) {
2262            $this->log(__METHOD__ . ' error -->' . json_encode($accessTokenData) . "\n | params --> " . json_encode($params), 'debug');
2263            return false;
2264        }
2265
2266        $createOrderParams = array(
2267            'accessToken' => $accessTokenData['access_token'],
2268            'paypalRequestId' => (isset($pt['id']) && $pt['id']) ? $pt['id'] : (isset($apt['id']) ? $apt['id'] : $lpt['id']),
2269            'intent' => 'CAPTURE',
2270            'paymentHash' => $paymentHash,
2271            'userId' => $userId,
2272            'currencyCode' => $currencyCode,
2273            'amount' => (int)$totalReceivableAmount,
2274            'billingAgreementId' => $params['paypal_billing_agreement_id']
2275        );
2276
2277        // void authorization
2278        $orderResult = $paypal->createOrder($createOrderParams);
2279        $paymentSuccess = isset($orderResult['status']) && $orderResult['status'] == 'COMPLETED' ? true : false;
2280        $this->loadModel('Payment');
2281
2282        // Reservation payment
2283        if( $receivableAmount > 0 ) {
2284            $savePaymentArr = array(
2285                'user_id' => $userId,
2286                'type_id' => 2,
2287                'pay_kbn' => 1,
2288                'reference_id' => $userId,
2289                'payment_transaction_password' => $paymentSuccess ? $pt['password'] : '',
2290                'status' => $paymentSuccess ? 1 : '',
2291                'form_type' => Configure::read('payment_credit_receivable'),
2292                'ordd' => $paymentSuccess ? $paymentHash : '',
2293                'amount' => $receivableAmount,
2294                'param1' => json_encode($orderResult),
2295                'param2' => $paymentSuccess ? '' : 'error',
2296                'card_company' => Configure::read('card_company.paypal'),
2297                'transaction_code' => $paymentSuccess ? $paymentHash : '',
2298                'currency_id' => Configure::read('default.settlement_currency_id'),
2299                'currency_code' => $currencyCode,
2300                'payment_id' => $paymentPlanId,
2301                'price_id' => $priceId,
2302                'payment_type' => Configure::read('payment_types.payment_receivable'),
2303                'logFileName' => 'debug'
2304            );
2305
2306            // create new payment
2307            $paymentSave = $this->Payment->rawSavePayment($savePaymentArr);
2308        }
2309
2310        // Appreciation payment
2311        if( $appreciationReceivableAmount > 0 ) {
2312            $savePaymentArr = array(
2313                'user_id' => $userId,
2314                'type_id' => 2,
2315                'pay_kbn' => 1,
2316                'reference_id' => $userId,
2317                'payment_transaction_password' => $paymentSuccess ?($pt['password'] ?? ''): '',
2318                'status' => $paymentSuccess ? 1 : '',
2319                'form_type' => Configure::read('payment_credit_appreciation_receivable'),
2320                'ordd' => $paymentSuccess ? $paymentHash : '',
2321                'amount' => $appreciationReceivableAmount,
2322                'param1' => json_encode($orderResult),
2323                'param2' => $paymentSuccess ? '' : 'error',
2324                'card_company' => Configure::read('card_company.paypal'),
2325                'transaction_code' => $paymentSuccess ? $paymentHash : '',
2326                'currency_id' => Configure::read('default.settlement_currency_id'),
2327                'currency_code' => $currencyCode,
2328                'payment_id' => $paymentPlanId,
2329                'price_id' => $priceId,
2330                'payment_type' => Configure::read('payment_types.payment_receivable'),
2331                'logFileName' => 'debug'
2332            );
2333
2334            // create new payment
2335            $paymentSave = $this->Payment->rawSavePayment($savePaymentArr);
2336        }
2337
2338        // Live payment
2339        if( $liveReceivableAmount > 0 ) {
2340            $savePaymentArr = array(
2341                'user_id' => $userId,
2342                'type_id' => 2,
2343                'pay_kbn' => 1,
2344                'reference_id' => $userId,
2345                'payment_transaction_password' => $paymentSuccess ? ($pt['password'] ?? '') : '',
2346                'status' => $paymentSuccess ? 1 : '',
2347                'form_type' => Configure::read('payment_live_lesson_receivable'),
2348                'ordd' => $paymentSuccess ? $paymentHash : '',
2349                'amount' => $liveReceivableAmount,
2350                'param1' => json_encode($orderResult),
2351                'param2' => $paymentSuccess ? '' : 'error',
2352                'card_company' => Configure::read('card_company.paypal'),
2353                'transaction_code' => $paymentSuccess ? $paymentHash : '',
2354                'currency_id' => Configure::read('default.settlement_currency_id'),
2355                'currency_code' => $currencyCode,
2356                'payment_id' => $paymentPlanId,
2357                'price_id' => $priceId,
2358                'payment_type' => Configure::read('payment_types.payment_receivable'),
2359                'logFileName' => 'debug'
2360            );
2361
2362            // create new payment
2363            $paymentSave = $this->Payment->rawSavePayment($savePaymentArr);
2364        }        
2365
2366        if ($paymentSave && $paymentSuccess) {
2367
2368            // Update Reservation payment receivables
2369            if( $receivableAmount > 0 ) {
2370                // get payment id
2371                $paymentData = $this->Payment->find('first', array(
2372                    'fields' => array(),
2373                    'conditions' => array(
2374                        'user_id' => $userId,
2375                        'form_type' => Configure::read('payment_credit_receivable'),
2376                        'ordd' => $paymentHash
2377                    ),
2378                    'recursive' => -1
2379                ));
2380
2381                if ($paymentData) {
2382                    $this->loadModel('PaymentReceivable');
2383                    // set payment receivable statuses to 2 - received
2384                    $this->PaymentReceivable->updateReceivableReservationPayment(
2385                        $userId,
2386                        array(
2387                            'status' => 2,
2388                            'payment_id' => $paymentData['Payment']['id'],
2389                            'payment_collection_date' => date("Y-m-d H:i:s"),
2390                            'card_company' => Configure::read('card_company.paypal'),
2391                            'payment_plan_id' => $paymentPlanId,
2392                            'membership_type_index' => $membershipStatusIndex
2393                        ),
2394                        array(
2395                            'PaymentReceivable.user_id' => $userId,
2396                            'PaymentReceivable.status' => 0,
2397                            'PaymentReceivable.payment_element_type' => 1,
2398                            'PaymentReceivable.created <=' => date('Y-m-d H:i:s')
2399                        )
2400                    );
2401                }
2402            }
2403
2404            // Update Appreciation payment receivables
2405            if( $appreciationReceivableAmount > 0 ) {
2406                // get payment id
2407                $paymentData = $this->Payment->find('first', array(
2408                    'fields' => array(),
2409                    'conditions' => array(
2410                        'user_id' => $userId,
2411                        'form_type' => Configure::read('payment_credit_appreciation_receivable'),
2412                        'ordd' => $paymentHash
2413                    ),
2414                    'recursive' => -1
2415                ));
2416
2417                if ($paymentData) {
2418                    $this->loadModel('PaymentReceivable');
2419                    // set payment receivable statuses to 2 - received
2420                    $this->PaymentReceivable->updateReceivableReservationPayment(
2421                        $userId,
2422                        array(
2423                            'status' => 2,
2424                            'payment_id' => $paymentData['Payment']['id'],
2425                            'payment_collection_date' => date("Y-m-d H:i:s"),
2426                            'card_company' => Configure::read('card_company.paypal'),
2427                            'payment_plan_id' => $paymentPlanId,
2428                            'membership_type_index' => $membershipStatusIndex
2429                        ),
2430                        array(
2431                            'PaymentReceivable.user_id' => $userId,
2432                            'PaymentReceivable.status' => 0,
2433                            'PaymentReceivable.payment_element_type' => Configure::read('appreciation_data.payment_element_type'),
2434                            'PaymentReceivable.created <=' => date('Y-m-d H:i:s')
2435                        )
2436                    );
2437                }
2438            }
2439
2440            // Update live payment receivables
2441            if( $liveReceivableAmount > 0 ) {
2442                // get payment id
2443                $paymentData = $this->Payment->find('first', array(
2444                    'fields' => array(),
2445                    'conditions' => array(
2446                        'user_id' => $userId,
2447                        'form_type' => Configure::read('payment_live_lesson_receivable'),
2448                        'ordd' => $paymentHash
2449                    ),
2450                    'recursive' => -1
2451                ));
2452
2453                if ($paymentData) {
2454                    $this->loadModel('PaymentReceivable');
2455                    // set payment receivable statuses to 2 - received
2456                    $this->PaymentReceivable->updateReceivableReservationPayment(
2457                        $userId,
2458                        array(
2459                            'status' => 2,
2460                            'payment_id' => $paymentData['Payment']['id'],
2461                            'payment_collection_date' => date("Y-m-d H:i:s"),
2462                            'card_company' => Configure::read('card_company.paypal'),
2463                            'payment_plan_id' => $paymentPlanId,
2464                            'membership_type_index' => $membershipStatusIndex                            
2465                        ),
2466                        array(
2467                            'PaymentReceivable.user_id' => $userId,
2468                            'PaymentReceivable.status' => 0,
2469                            'PaymentReceivable.payment_element_type' => 3,
2470                            'PaymentReceivable.created <=' => date('Y-m-d H:i:s')
2471                        )
2472                    );
2473                }
2474            }            
2475
2476        }
2477        if( isset($pt['id']) ) {
2478            $ptUpdateParams = array(
2479                'id' => $pt['id'],
2480                'fields' => array(
2481                    'status' => $paymentSuccess ? 1 : 2,
2482                    'response_text' => $orderResult
2483                ),
2484                'logFileName' => 'debug'
2485            );
2486
2487            // update payment transaction
2488            if (!$this->PaymentTransaction->updateWPPaymentTransaction($ptUpdateParams)) {
2489                $this->log(__METHOD__ . ' Cannot update payment transaction. --> ' . json_encode($ptUpdateParams), 'debug');
2490            }
2491        }
2492
2493        if( isset($apt['id']) ) {
2494            $ptUpdateParams = array(
2495                'id' => $apt['id'],
2496                'fields' => array(
2497                    'status' => $paymentSuccess ? 1 : 2,
2498                    'response_text' => $orderResult
2499                ),
2500                'logFileName' => 'debug'
2501            );
2502            // update payment transaction
2503            if (!$this->PaymentTransaction->updateWPPaymentTransaction($ptUpdateParams)) {
2504                $this->log(__METHOD__ . ' Cannot update payment transaction. --> ' . json_encode($ptUpdateParams), 'debug');
2505            }
2506        }
2507
2508        if( isset($lpt['id']) ) {
2509            $ptUpdateParams = array(
2510                'id' => $lpt['id'],
2511                'fields' => array(
2512                    'status' => $paymentSuccess ? 1 : 2,
2513                    'response_text' => $orderResult
2514                ),
2515                'logFileName' => 'debug'
2516            );
2517            // update payment transaction
2518            if (!$this->PaymentTransaction->updateWPPaymentTransaction($ptUpdateParams)) {
2519                $this->log(__METHOD__ . ' Cannot update payment transaction. --> ' . json_encode($ptUpdateParams), 'debug');
2520            }
2521        }        
2522
2523        // log
2524        $this->log(__METHOD__ . "::PaymentReceivable charge on withdrawal. \nData: " . json_encode(array('params' => $params, 'result' => $orderResult)), 'debug');
2525    }
2526
2527    /**
2528    * Settle payment receivables 
2529    * @param array user data
2530    * @return boolean
2531    */
2532    protected function chargePaymentReceivable($params = array()) {
2533        //validate need data for payment receivable
2534        if (
2535            empty($params['id']) ||
2536            empty($params['email']) ||
2537            empty($params['currency_code']) ||
2538            empty($params['payment_plan_id']) ||
2539            empty($params['price_id']) ||
2540            empty($params['card_company']) 
2541        )
2542        {
2543            $this->log(__METHOD__ . "error data pass. Data : " . json_encode($params), 'debug');
2544            return false;
2545        }
2546
2547        $userId = $params['id'];
2548        $currencyCode = $params['currency_code'];
2549        $paymentPlanId = $params['payment_plan_id'];
2550        $priceId = $params['price_id'];
2551
2552        // set db connection
2553        $db = ConnectionManager::getDataSource('default');
2554        //db resources reconnect
2555        if ($db->isConnected()) {
2556            $db->close(); // stop
2557        }
2558        $db->reconnect();        
2559
2560        $rawQuery = "
2561            SELECT 
2562                SUM(`amount`) as `amount`
2563            FROM
2564                `payment_receivables`
2565            WHERE
2566                `payment_receivables`.`user_id` = {$userId}
2567                AND `payment_receivables`.`status` = 0
2568                AND `payment_receivables`.`payment_element_type` IN (1 , 2, 3)
2569                AND `payment_receivables`.`created` <= NOW();
2570        ";
2571        $result = $this->User->query($rawQuery);
2572
2573        //check payment receivable
2574        if (!isset($result[0][0]['amount']) || empty($result[0][0]['amount'])) {
2575            $this->log(__METHOD__ . "::No payment receivable. \n Data : " . json_encode($params), 'debug');
2576            return false;
2577        }
2578
2579        //get payment receivable
2580        $receivablePayment = $result[0][0]['amount'];        
2581
2582        //generate ordd code
2583        $paymentHash = myTools::generateOrderCode($userId);
2584        $familyId = null;
2585
2586        $paymentParams = array(
2587            'currencyCode' => $currencyCode,
2588            'formType' => Configure::read('payment_credit_receivable'),
2589            'paymentType' => Configure::read('payment_types.payment_receivable'),
2590            'logFileName' => 'debug',
2591            'paymentAmount' => $receivablePayment,
2592            'familyId' => $familyId,
2593            'priceId' => $priceId,
2594            'paymentPlanId' => $paymentPlanId
2595        );
2596
2597        // if corporate user
2598        if (isset($params['corporate_id'])) {
2599            $paymentParams['corporateSettlementType'] = Configure::read('corporate_settlement_types.receivable_reservation_payment');
2600        }
2601
2602        $ptParams = array(
2603            'userId' => $userId,
2604            'status' => 0,
2605            'paymentHash' => $paymentHash,
2606            'paymentParams' => json_encode($paymentParams),
2607            'responseText' => '',
2608            'logFileName' => 'debug'
2609        );
2610
2611        //db resources reconnect
2612        if ($db->isConnected()) {
2613            $db->close(); // stop
2614        }
2615        $db->reconnect();
2616
2617        // create payment transaction
2618        if (!$pt = $this->PaymentTransaction->rawSaveCronPaymentTransaction($ptParams)) {
2619            $this->log(__METHOD__ . "::Cannot create payment transaction. \nData:" .json_encode($ptParams), 'debug');
2620            return false;            
2621        }
2622
2623        //db resources reconnect
2624        if ($db->isConnected()) {
2625            $db->close(); // stop
2626        }
2627        $db->reconnect();
2628
2629        //default user data
2630        $clientIp = PaymentTable::getClientIpByCompanyId($params['card_company']);
2631        $email = $params['email'];
2632        $sendId = $params['id'];
2633
2634        //set payment data
2635        $params = array(
2636            'clientIp' => $clientIp,
2637            'email' => $email,
2638            'sendId' => $sendId,
2639            'money' => $receivablePayment,
2640            'paymentHash' => $paymentHash
2641        );    
2642
2643        $fallBackPayment = ZChargeComponent::charge_with_regsterd_card(json_encode($params));
2644
2645        // log
2646        $this->log(__METHOD__ . "::PaymentReceivable charge on withdrawal. \nData: " . json_encode(array('params' => $params, 'result' => $fallBackPayment)), 'debug');
2647    }
2648
2649    /**
2650    * Charge worlplay users on withdraw
2651    * @param array - user data
2652    * @return boolean
2653    */
2654    protected function wpChargePaymentReceivable($params = array()) {
2655        if (
2656            empty($params['id']) ||
2657            empty($params['email']) ||
2658            empty($params['currency_code']) ||
2659            empty($params['payment_plan_id']) ||
2660            empty($params['price_id']) ||
2661            empty($params['card_token'])
2662        ) {
2663            $this->log(__METHOD__ . "::Missing parameters. \nData : ". json_encode($params), 'debug');
2664            return false;
2665        }
2666
2667        // set db connection
2668        $db = ConnectionManager::getDataSource('default');
2669
2670        //db resources reconnect
2671        if ($db->isConnected()) {
2672            $db->close(); // stop
2673        }
2674        $db->reconnect();        
2675
2676        $userId = $params['id'];
2677
2678        $rawQuery = "SELECT 
2679                (SELECT 
2680                        SUM(`amount`) AS `amount`
2681                    FROM
2682                        `payment_receivables`
2683                    WHERE
2684                        `payment_receivables`.`user_id` = u.id
2685                            AND `payment_receivables`.`status` = 0
2686                            AND `payment_receivables`.`payment_element_type` in (1,2,3)
2687                            AND `payment_receivables`.`created` <= NOW()) AS receivables
2688            FROM  users AS u WHERE u.id = {$userId}
2689        ";
2690
2691        $result = $this->User->query($rawQuery);
2692
2693        $totalReceivableAmount = isset( $result[0][0]['receivables'] ) && $result[0][0]['receivables'] ? $result[0][0]['receivables'] : 0 ;
2694
2695        //check payment receivable
2696        if ( $totalReceivableAmount < 1 ) {
2697            $this->log(__METHOD__ . "::No payment receivable. \n Data : " . json_encode($params), 'debug');
2698            return false;
2699        }      
2700
2701        $email = $params['email'];
2702        $currencyCode = $params['currency_code'];
2703        $paymentPlanId = $params['payment_plan_id'];
2704        $priceId = $params['price_id'];
2705        $receivableFormType = Configure::read('payment_credit_receivable');
2706        $currencyExponents = Configure::read('worldpay.currency_exponents');
2707        $receivableOrderCode = myTools::generateOrderCode($userId);
2708        $paymentMethodType = myTools::getWPPaymentMethodType($params['card_brand'], 'payment');
2709        $merchantCode = myTools::getWPMerchantCode($paymentMethodType);
2710        $paymentMethod = explode('_', $paymentMethodType);
2711        $paymentMethod = isset($paymentMethod[0]) ? $paymentMethod[0] : null;
2712        $paymentPlanId = $paymentPlanId;
2713        $exponent = $currencyExponents[$currencyCode];
2714
2715        $receivablPaymentAmountArr = myTools::wpGetAmount($exponent, (float)$totalReceivableAmount);
2716        $ncAmount = $receivablPaymentAmountArr['ncAmount'];
2717        $wpAmount = $receivablPaymentAmountArr['wpAmount'];
2718        $membershipStatusIndex = UserTable::getStudentMembershipStatus($userId);
2719
2720        // Appreciation and Reservation payment transaction
2721        if( $totalReceivableAmount > 0 ) {
2722            $ptParams = array(
2723                'userId' => $userId,
2724                'status' => 0,
2725                'paymentHash' => $receivableOrderCode,
2726                'paymentParams' => json_encode(array(
2727                    'currencyCode' => $currencyCode,
2728                    'formType' => $receivableFormType,
2729                    'paymentType' => Configure::read('payment_types.payment_receivable'),
2730                    'logFileName' => 'debug',
2731                    'wpPaymentAmount' => $wpAmount,
2732                    'paymentAmount' => $ncAmount,
2733                    'cronDateRun' => $this->cronDateTime,
2734                    'priceId' => $priceId,
2735                    'paymentPlanId' => $paymentPlanId,
2736                    'merchantCode' => $merchantCode,
2737                    'membershipStatusIndex' => $membershipStatusIndex
2738                )),
2739                'responseText' => '',
2740                'logFileName' => 'debug'
2741            );
2742
2743            // create payment transaction
2744            if (!$pt = $this->PaymentTransaction->rawSaveCronPaymentTransaction($ptParams)) {
2745                $this->log(__METHOD__ . "::Cannot create payment transaction. \nData:" .json_encode($ptParams), 'debug');
2746                return false;
2747            }
2748        }
2749
2750        //set payment params
2751        $chargeParams = array(
2752            'merchantCode' => $merchantCode,
2753            'orderCode' => $receivableOrderCode,
2754            'description' => 'Payment Credit Receivable',
2755            'currencyCode' => $currencyCode,
2756            'exponent' => $exponent,
2757            'amount' => $wpAmount,
2758            'cardToken' => $params['card_token'],
2759            'email' => $email,
2760            'authenticatedShopperId' => $userId,
2761            'xmlName' => 'direct_payment_with_token',
2762            'shopperIpAddress' => '52.193.149.250', // ncweb6 server ip address
2763            'wpTransactionIdentifier' => $params['wp_transaction_identifier'],
2764            'paymentMethod' => $paymentMethod
2765        );        
2766
2767        $receivableResult = wpPaymentService::directPayment($chargeParams);
2768
2769        //check direct payment result
2770        if (!myTools::checkIfWPPaymentResponseIsAuthorised($receivableResult)) {
2771            $receivableStatus = 2; // error
2772        }
2773
2774        //db resources reconnect
2775        if ($db->isConnected()) {
2776            $db->close(); // stop
2777        }
2778        $db->reconnect();     
2779
2780        $this->PaymentTransaction->rawCronUpdatePaymentTransactionResponseTextAndStatus(array(
2781            'orderCode' => $receivableOrderCode,
2782            'responseText' => json_encode(array('cronMonthlyPaymentReceivable_response' => $receivableResult)),
2783            'status' => isset($receivableStatus) ? $receivableStatus : 2, // 1 - success, 2 - error
2784            'logFileName' => 'debug'
2785        ));
2786    }
2787
2788    public function setSeoLocalizeUrl() {
2789        $hasLocalizeSupport = true; // default
2790        $con = $this->params->params['controller'];
2791        $action = $this->params->params['action'];
2792
2793        // add controller and/or action for the web pages that will not be applied in the tags for SEO
2794        // if ($con == 'MyPage' && $action == 'index') { // --> this is just a sample
2795        //     $hasLocalizeSupport = false;
2796        // }
2797
2798        if (!$hasLocalizeSupport || $this->localizeDir == Configure::read('default.user_language')) {
2799            $seoLocalizeUrl = myTools::getUrl();
2800        } else {
2801            $seoLocalizeUrl = myTools::getUrl() . '/' . $this->localizeDir;
2802        }
2803
2804        $this->set('hasLocalizeSupport', $hasLocalizeSupport);
2805        $this->set('seoLocalizeUrl', $seoLocalizeUrl);
2806    }
2807
2808    /**
2809     * get currency code using user's currency code or local language directory currency code equivalent.
2810     */
2811    public function getCustomCurrencyCode() {
2812        return isset($this->sharedUserData['User']['currency_code']) ? $this->sharedUserData['User']['currency_code'] : (isset($this->localizeDir) && is_string($this->localizeDir) && isset($this->allowedCurrencies[$this->localizeDir]) ? $this->allowedCurrencies[$this->localizeDir] : Configure::read('default.user_currency'));
2813    }
2814
2815    /**
2816     * get premium plan price
2817     */
2818    public function getPremiumPlanPrice($params = []) {
2819        $logFileName = isset($params['logFileName']) ? $params['logFileName'] : null;
2820        $currencyCode = isset($params['currencyCode']) ? $params['currencyCode'] : null;
2821        $numberFormatFlg = isset($params['numberFormatFlg']) ? $params['numberFormatFlg'] : true;
2822        if (!isset($currencyCode)) {
2823            $currencyCode = $this->getCustomCurrencyCode();
2824        }
2825
2826
2827        $this->loadModel('PaymentPlanPrice');
2828        $amount = $this->PaymentPlanPrice->getMonthlyPrice(array(
2829            'currencyCode' => $currencyCode,
2830            'paymentPlanId' => Configure::read('payment_plans.premium_plan'),
2831            'numberFormatFlg' => $numberFormatFlg,
2832            'logFileName' => $logFileName
2833        ));
2834
2835        return $amount;
2836    }
2837
2838    /**
2839     * NC-7922: Stasapu cs admin domains not allowed access on user
2840    */
2841    private function checkStasapuDomain() {
2842        $env = Configure::read('ENVIRONMENT');
2843        $stasapuDomainArr = Configure::read('stasapucs_host');
2844        $getDomainArr = parse_url($_SERVER['HTTP_HOST']);
2845        $host = isset($getDomainArr['path']) ? $getDomainArr['path'] : null;
2846        if ( isset($stasapuDomainArr[$env]) && $host ) {
2847            if ( $host == $stasapuDomainArr[$env] ) {
2848                throw new NotFoundException();
2849            }
2850        }
2851    }
2852
2853    public function disablePageForSapuri($page='pc') {
2854        if ($page == 'pc' && $this->Auth->loggedIn() && $this->isStudySapuriUser) {
2855            return $this->isStudySapuriTosUser ? $this->redirect('/lesson-reservation') : $this->redirect('/mypage');
2856        }
2857
2858        if ($page == 'mobapp' && isset($this->request->query['token']) && $this->isStudySapuriUser) {
2859            // return $this->redirect('/mobapp/close?token='.$this->request->query['token']);
2860            return $this->redirect('/?plan=not_supported'.$this->request->query['token']);
2861        }
2862    }
2863    /**
2864     * block free user from sapuri toS student
2865     */
2866    public function blockWithdrawnSapuriToS($page = 'pc') {
2867        $token = !empty($this->request->query['token']) ? $this->request->query['token'] : null;
2868        $userId = null;
2869        $checkRes = [];
2870
2871        if ($page == 'mobapp' && $token) {
2872            $user = UserTable::validToken($token);
2873            $userId = isset($user['User']['id']) ? $user['User']['id'] : $userId;
2874        }
2875
2876        if ($page == 'pc' && $this->Auth->loggedIn()) {
2877            $userId = $this->Auth->user('id');
2878        }
2879
2880        if ($userId) {
2881            $usersExtend = ClassRegistry::init('UsersExtend');
2882            $usersExtend->openDBReplica();
2883            $checkRes = $usersExtend->find('first', [
2884                'conditions' => ['UsersExtend.user_id' => $userId]
2885            ]);
2886            $usersExtend->closeDBReplica();
2887        }
2888
2889        if (isset($checkRes) && count($checkRes)) {
2890            $redirectUrl = ($page == 'mobapp') ? '/mobapp/close?token='.$token : '/mypage';
2891            return $this->redirect($redirectUrl);
2892        }
2893    }
2894
2895    /**
2896     * NC-8916: create english hub cookie
2897    */
2898    private function createEnglishHubCookie() {
2899        $indexCookieStr = null;
2900        $p = "";
2901        $cid = "";
2902        
2903        // check cid and p params for ehub
2904        if ( 
2905                ( isset($this->request->query['cid']) && $this->request->query['cid'] ) && 
2906                ( isset($this->request->query['p']) && $this->request->query['p'] )
2907            )
2908        {
2909            $cid = $this->request->query['cid'];
2910            $p = $this->request->query['p'];
2911            
2912            // create index
2913            $indexCookieStr = "CL_".$p;
2914            $this->Cookie->write($indexCookieStr, $cid, false, Configure::read("cookieTime"));
2915        }
2916
2917        // check if campaign code for english hub is not set but english hub params are present
2918        if ( 
2919            // - if has index
2920            $indexCookieStr && 
2921            
2922            // - if current campaign_code is not from english hub
2923            ( 
2924                !$this->Cookie->check('campaign_code') || 
2925                
2926                // - has cookie data, but not enlish_hub cookie
2927                ( 
2928                    $this->Cookie->check('campaign_code') && 
2929                    $this->Cookie->read('campaign_code') != Configure::read("english_hub_affiliate_cc") 
2930                )
2931            )
2932            
2933            // - if from affee -> do not run campaign_code
2934            && $p != "phdiu0vd8jvm"
2935        ) {
2936            // create english hub cookie
2937            $this->Cookie->write('campaign_code',Configure::read("english_hub_affiliate_cc"), true, Configure::read("cookieTime") );
2938        }
2939        
2940        return $indexCookieStr;
2941    }
2942
2943    public function checkControllerActionExist($controller, $action) {
2944        $controller = Inflector::camelize($controller);
2945        $m_controller = $controller.'Controller';
2946        App::import('Controller', $m_controller);
2947
2948        if (!class_exists($m_controller)) return false;
2949
2950        $aMethods = get_class_methods($m_controller);
2951        if ($aMethods) {
2952            foreach ($aMethods as $idx => $method) {
2953                if($action==$method) return true;
2954            }
2955        } else  {
2956            //this is probably NOT a controller!
2957        }
2958        return false;
2959    }
2960
2961    /**
2962     * NC-9586: check if from SNS share
2963    */
2964    public function checkIfSNSShare(){
2965        if(
2966            isset($_GET["nc_share_ref"]) &&
2967            $_GET["nc_share_ref"] == "nc_sns_share" &&
2968            isset($_SERVER["HTTP_USER_AGENT"]) && 
2969            (
2970                (strpos($_SERVER["HTTP_USER_AGENT"], 'facebookexternalhit') !== false) ||
2971                (strpos($_SERVER["HTTP_USER_AGENT"], 'Twitterbot') !== false) ||
2972                (strpos($_SERVER["HTTP_USER_AGENT"], 'line-poker') !== false)
2973            )
2974        ){
2975            return true;
2976        }
2977
2978        return false;
2979    }
2980
2981
2982    /**
2983    * fetch user's appreciation options data for modal display
2984    * @param : array( 'chat_hash' => str )
2985    * @return : array( 'html_element' => str[html element] )
2986    */
2987    public function setUpAppreciationSelectionModalElement( $params = array() ) {
2988        $result = array();
2989        $chatHash = isset($params['chat_hash']) && $params['chat_hash'] ? $params['chat_hash'] : null ;
2990        if ( $chatHash ) {
2991
2992            $fetchAppreciationData = $this->LessonOnairsLog->fetchAppreciationOptionToTeacher(array( 'chat_hash' => $chatHash));
2993            if( 
2994                (isset($fetchAppreciationData['data']) && $fetchAppreciationData['data']) && 
2995                (
2996                    (isset($fetchAppreciationData['user_tips_appreciation_flg']) && $fetchAppreciationData['user_tips_appreciation_flg'] == 1) ||
2997                    (isset($fetchAppreciationData['user_message_appreciation_flg']) && $fetchAppreciationData['user_message_appreciation_flg'] == 1)
2998                )
2999            ) { // check data option available user_appreciation_flg
3000                $appreciationGroupAmountLogDataArr = $fetchAppreciationData['data'];
3001                $teacherteacherDataObj= new TeacherTable($fetchAppreciationData['teacher_data']);
3002
3003                // set default details var, normal teacher
3004                $_name = $teacherteacherDataObj->name;
3005                $_jp_name = $teacherteacherDataObj->jp_name;
3006                $_image_url = $teacherteacherDataObj->getImageUrl();
3007
3008                // if counselor teacher, set details var for counselor
3009                if(isset($teacherteacherDataObj->counseling_flg) && $teacherteacherDataObj->counseling_flg){
3010                    // get counselor default img
3011                    $counselorImageUrl = $teacherteacherDataObj->getProfileImage(Configure::read('default_counselor_detail'));
3012
3013                    // counselor data
3014                    $_name = 'Counselor';
3015                    $_jp_name = 'カウンセラー';
3016                    $_image_url = $counselorImageUrl['image_url'];
3017                }
3018
3019                // if avatar teacher, set details var for avatar parent
3020                if (
3021                    (isset($teacherteacherDataObj->avatar_id) && $teacherteacherDataObj->avatar_id) && 
3022                    (isset($teacherteacherDataObj->avatar_flg) && $teacherteacherDataObj->avatar_flg)
3023                ) {
3024                    // avatar parent data
3025                    $_name = $teacherteacherDataObj->getAvatarParentNameEn();
3026                    $_jp_name =  $teacherteacherDataObj->getAvatarParentName();
3027                    $_image_url = $teacherteacherDataObj->getAvatarParentImageUrl();
3028                }
3029
3030                // set teacher data for view
3031                $teacherData = array(
3032                    'id' => $teacherteacherDataObj->id,
3033                    'name' => $_name,
3034                    'jp_name' => $_jp_name,
3035                    'image_url' => $_image_url
3036                );
3037
3038                // - user data obj
3039                $userData = new UserTable($this->sharedUserData['User']);
3040
3041                // - user appreciation message/tips behavior NJ-53624
3042                $getTeacherCoinBoxData = $this->TeacherCoinBox->isHashExists($params['chat_hash'], $this->Auth->user('id'));
3043                $element_message = '';
3044                $tipShow = $fetchAppreciationData['user_tips_appreciation_flg'];
3045                $has_no_tips_yet = 1;
3046                if (!empty($getTeacherCoinBoxData)){
3047                    $element_message = $getTeacherCoinBoxData['TeacherCoinBox']['element_message'];
3048                    $has_no_tips_yet = $getTeacherCoinBoxData['TeacherCoinBox']['has_tips'] == 1 ? 0 : 1;
3049                }
3050                $finalTipShow = $tipShow == 1 ? $has_no_tips_yet : $tipShow;
3051                $view = new View($this, false);
3052                $appreciation_selection_modal_params = array(
3053                    'element_message' => $element_message,
3054                    'optionArr' => $appreciationGroupAmountLogDataArr,
3055                    'teacherArr' => $teacherData,
3056                    'chat_hash' => $chatHash,
3057                    'user_tips_appreciation_flg' => $finalTipShow,
3058                    'user_message_appreciation_flg' => $fetchAppreciationData['user_message_appreciation_flg'],
3059                    'card_company' => $this->sharedUserData['User']['card_company'],
3060                    'usersPointDetail' => $fetchAppreciationData['user_purchase_coin'] //NJ-12246: Get usersPointData
3061                );
3062
3063                //- NJ-23781 : get individual card flg if corporate users (card and bank transfer)
3064                if(in_array($userData->getMembershipTypeIndex(), Configure::read('corp_personal_card_payment_valid_memberships'))){
3065                    $getICFFlg = $this->UsersDetail->getCorpIndividualCardFlg(['user_id' => $this->Auth->user('id')]);
3066                    if($getICFFlg){
3067                        $appreciation_selection_modal_params['corp_individual_card_fail_flg'] = $getICFFlg['individual_card_fail_flg'];
3068                    }
3069                }
3070                if (
3071                    isset($fetchAppreciationData['user_message_appreciation_flg']) && $fetchAppreciationData['user_message_appreciation_flg'] == 1
3072                    ||
3073                    $finalTipShow == 1
3074                ){
3075                    $result['html_element'] = $view->element('appreciation_selection_modal', $appreciation_selection_modal_params);
3076                }
3077            }
3078
3079        }
3080        return $result;
3081    }
3082    /**
3083    * Send teacher's appreciation
3084    * @param : array( 'appreciation_id' => int, 'message' => str, 'chat_hash' => str )
3085    * @return : bool
3086    */
3087    public function sendTeacherAppreciation( $params = array() ) {
3088        $result = array( 'result' => 0 ); // false 
3089        $appreciationId = isset( $params['appreciation_id'] ) ? $params['appreciation_id'] : null; 
3090        $tipCoin = isset( $params['tip_coin'] ) ? $params['tip_coin'] : null;
3091        $message = isset( $params['message'] ) && $params['message'] ? $params['message'] : null; 
3092        $chathash = isset( $params['chat_hash'] ) && $params['chat_hash'] ? $params['chat_hash'] : null; 
3093        $action_mode = isset( $params['action_mode'] ) ? $params['action_mode'] : 0; 
3094
3095        $userData = $this->sharedUserData;
3096        $userID = $userData['User']['id'];
3097
3098        //fetch the show appreciation flg;show_appreciation_flg
3099        $userData = $this->User->find("first",array(
3100            'fields' => array(
3101                "User.show_appreciation_flg",
3102                "User.display_appreciation_message_flg"
3103            ),
3104            'conditions' => array(
3105                'User.id' => $userID
3106            )
3107        ));
3108
3109        $userData = $userData['User'] ?? array();
3110        $showAppreciationFlg = $userData['show_appreciation_flg'] ?? 0;
3111
3112        $showAppreciationMessageFlg = $userData['display_appreciation_message_flg'] ?? 0;
3113
3114        $sendParam = array(
3115            'chat_hash'  => $chathash,
3116            'appreciation_id'  => $appreciationId,
3117            'tip_coin'  => $tipCoin,
3118            'message' => $message,
3119            'access_point' => 'pc',
3120            'action_mode' => $action_mode
3121        );
3122
3123        //send the appreciation to teacher if flag is 1 
3124        if ((int)$showAppreciationFlg == 1 || (int)$showAppreciationMessageFlg == 1) {
3125            $sendData = $this->LessonOnairsLog->sendAppreciationToTeacher($sendParam);
3126            if ( isset ($sendData['result'] ) && $sendData['result'] ) {
3127                // set default res
3128                $result = array( 'result' => 1 );
3129
3130                // set return appreciation item
3131                $result['appreciation_details'] = $sendData['appreciation_item'];
3132
3133            } else {
3134                if( isset ($sendData['error'] ) && $sendData['error'] ){
3135                    $result['error']['id'] = 'sending_failed';
3136                    $result['error']['message'] = json_encode($sendData['error']);
3137                }
3138            }
3139        }else{
3140            $result['error']['id'] = 'show_flag_invalid';
3141            $result['error']['message'] = "Appreciation Show Flag is invalid, flag must be set to 'On' on the account settings";
3142        }
3143
3144        return $result;
3145    }
3146
3147    public function isLocalizeDirValid($code) {
3148
3149        $this->CountryCode->openDBReplica();
3150
3151        $result = $this->CountryCode->find('count', array(
3152            'conditions' => array('CountryCode.iso_639_1' => $code),
3153            'recursive' => -1
3154        ));
3155
3156        $this->CountryCode->closeDBReplica();
3157
3158        return $result;
3159    }
3160
3161    /**
3162    * Settle aftee payment receivables
3163    * @param array user data
3164    * @return boolean
3165    */
3166    protected function chargeAfteePaymentReceivable($params = array()) {
3167        //validate need data for payment receivable
3168        if (
3169            empty($params['id']) ||
3170            empty($params['email']) ||
3171            empty($params['currency_code']) ||
3172            empty($params['payment_plan_id']) ||
3173            empty($params['price_id']) ||
3174            empty($params['card_company'])
3175        )
3176        {
3177            $this->log(__METHOD__ . "error data pass. Data : " . json_encode($params), 'debug');
3178            return false;
3179        }
3180
3181        $userId = $params['id'];
3182        $currencyCode = $params['currency_code'];
3183        $paymentPlanId = $params['payment_plan_id'];
3184        $priceId = $params['price_id'];
3185
3186        // set db connection
3187        $db = ConnectionManager::getDataSource('default');
3188        //db resources reconnect
3189        if ($db->isConnected()) {
3190            $db->close(); // stop
3191        }
3192        $db->reconnect();
3193
3194        $rawQuery = "SELECT 
3195                (SELECT 
3196                        SUM(`amount`) AS `amount`
3197                    FROM
3198                        `payment_receivables`
3199                    WHERE
3200                        `payment_receivables`.`user_id` = u.id
3201                            AND `payment_receivables`.`status` = 0
3202                            AND `payment_receivables`.`payment_element_type` = 1
3203                            AND `payment_receivables`.`created` <= NOW()) AS receivables,
3204                (SELECT 
3205                        SUM(`amount`) AS `amount`
3206                    FROM
3207                        `payment_receivables`
3208                    WHERE
3209                        `payment_receivables`.`user_id` = u.id
3210                            AND `payment_receivables`.`status` = 0
3211                            AND `payment_receivables`.`payment_element_type` = 2
3212                            AND `payment_receivables`.`created` <= NOW()) AS appreciation_receivables,
3213                (SELECT 
3214                        SUM(`amount`) AS `amount`
3215                    FROM
3216                        `payment_receivables`
3217                    WHERE
3218                        `payment_receivables`.`user_id` = u.id
3219                            AND `payment_receivables`.`status` = 0
3220                            AND `payment_receivables`.`payment_element_type` = 3
3221                            AND `payment_receivables`.`created` <= NOW()) AS live_receivables                        
3222            FROM  users AS u WHERE u.id = {$userId}
3223        ";
3224
3225        $result = $this->User->query($rawQuery);
3226
3227        $receivableAmount = isset( $result[0][0]['receivables'] ) && $result[0][0]['receivables'] ? $result[0][0]['receivables'] : 0 ;
3228        $appreciationReceivableAmount = isset( $result[0][0]['appreciation_receivables'] ) && $result[0][0]['appreciation_receivables'] ? $result[0][0]['appreciation_receivables'] : 0 ;
3229        $liveReceivableAmount = isset( $result[0][0]['live_receivables'] ) && $result[0][0]['live_receivables'] ? $result[0][0]['live_receivables'] : 0 ;
3230        $totalReceivableAmount = $receivableAmount + $appreciationReceivableAmount + $liveReceivableAmount;
3231
3232        // check payment receivable
3233        if ( $totalReceivableAmount < 1 ) {
3234            $this->log(__METHOD__ . "::No payment receivable. \n Data : " . json_encode($params), 'debug');
3235            return false;
3236        }
3237
3238        //generate ordd code
3239        $paymentHash = myTools::generateOrderCode($userId);
3240        $membershipStatusIndex = UserTable::getStudentMembershipStatus($userId);
3241        // Reservation payment transaction 
3242        if( $receivableAmount > 0 ) {
3243
3244            $paymentParams = array(
3245                'currencyCode' => $currencyCode,
3246                'formType' => Configure::read('payment_credit_receivable'),
3247                'paymentType' => Configure::read('payment_types.payment_receivable'),
3248                'logFileName' => 'debug',
3249                'paymentAmount' => $receivableAmount,
3250                'priceId' => $priceId,
3251                'paymentPlanId' => $paymentPlanId
3252            );
3253
3254            $ptParams = array(
3255                'user_id' => $userId,
3256                'payment_hash' => $paymentHash,
3257                'course_id' => Configure::read("credit.course_id"),
3258                'payment_params' => json_encode($paymentParams),
3259            );
3260
3261            // create payment transaction
3262            if (!$pt = $this->PaymentTransaction->setWPPaymentTransaction($ptParams)) {
3263                $this->log(__METHOD__ . "::Cannot create payment transaction. \nData:" .json_encode($ptParams), 'debug');
3264                return false;
3265            }
3266            
3267        }
3268        // Appreciation payment transaction
3269        if( $appreciationReceivableAmount > 0 ) {
3270
3271            $paymentParams = array(
3272                'currencyCode' => $currencyCode,
3273                'formType' => Configure::read('payment_credit_appreciation_receivable'),
3274                'paymentType' => Configure::read('payment_types.payment_receivable'),
3275                'logFileName' => 'debug',
3276                'paymentAmount' => $appreciationReceivableAmount,
3277                'priceId' => $priceId,
3278                'paymentPlanId' => $paymentPlanId
3279            );
3280
3281            $ptParams = array(
3282                'user_id' => $userId,
3283                'payment_hash' => $paymentHash,
3284                'course_id' => Configure::read("credit.course_id"),
3285                'payment_params' => json_encode($paymentParams),
3286            );
3287
3288            // create payment transaction
3289            if (!$apt = $this->PaymentTransaction->setWPPaymentTransaction($ptParams)) {
3290                $this->log(__METHOD__ . "::Cannot create payment transaction. \nData:" .json_encode($ptParams), 'debug');
3291                return false;
3292            }
3293
3294        }
3295
3296        // Live payment transaction
3297        if ($liveReceivableAmount > 0) {
3298
3299            $paymentParams = array(
3300                'currencyCode' => $currencyCode,
3301                'formType' => Configure::read('payment_live_lesson_receivable'),
3302                'paymentType' => Configure::read('payment_types.payment_receivable'),
3303                'logFileName' => 'debug',
3304                'paymentAmount' => $liveReceivableAmount,
3305                'priceId' => $priceId,
3306                'paymentPlanId' => $paymentPlanId
3307            );
3308
3309            $ptParams = array(
3310                'user_id' => $userId,
3311                'payment_hash' => $paymentHash,
3312                'course_id' => Configure::read("credit.course_id"),
3313                'payment_params' => json_encode($paymentParams),
3314            );
3315
3316            // create payment transaction
3317            if (!$lpt = $this->PaymentTransaction->setWPPaymentTransaction($ptParams)) {
3318                $this->log(__METHOD__ . "::Cannot create payment transaction. \nData:" .json_encode($ptParams), 'debug');
3319                return false;
3320            }
3321        }
3322
3323        //db resources reconnect
3324        if ($db->isConnected()) {
3325            $db->close(); // stop
3326        }
3327        $db->reconnect();
3328
3329        // load PayPal class
3330        if (!class_exists('AfteePaymentService')) {
3331            App::import('Lib', 'AfteePaymentService');
3332        }
3333
3334        $afteeChecksumData = array(
3335            'shopItemId' => "AFTEE" . Configure::read('payment_credit_receivable'),
3336            'itemName' => 'PaymentReceivables',
3337            'itemPrice' => (int)$totalReceivableAmount,
3338            'itemCount' => 1,
3339            'customerPhoneNumber' => $params['phone_number'],
3340            'customerEmail' => $params['email'],
3341            'shopTransactionNo' => $paymentHash,
3342            'userID' => $userId
3343        );
3344        $afteeService = new AfteePaymentService();
3345        $checksum = $afteeService->generateChecksum($afteeChecksumData, false);
3346        
3347
3348        $afteeData = array(
3349            'authentication_token' => $params['card_token'],
3350            'related_id' => $params['aftee_transaction_identifier'],
3351            'checksum' => $checksum['checksum'],
3352            'shop_transaction_no' => $paymentHash,
3353            'transaction_options' => array(1)
3354        );
3355
3356        $afteePaymentData = array_merge($afteeData, $checksum['settlementData']);
3357
3358        // process Aftee direct payment
3359        $res = $afteeService->directPayment($afteePaymentData);
3360        $checkRes = json_decode($res, true);
3361        $orderResult = $res;
3362
3363        if ( isset($checkRes['object']) && $checkRes['object'] == 'transaction') {
3364            $paymentSuccess = true;
3365        } else if ( !array_key_exists("object", $checkRes) || (isset($checkRes['object']) && $checkRes['object'] == 'error')) {
3366            $paymentSuccess = false;
3367        }
3368
3369        $this->loadModel('Payment');
3370
3371        // Reservation payment
3372        if( $receivableAmount > 0 ) {
3373            $savePaymentArr = array(
3374                'user_id' => $userId,
3375                'type_id' => 2,
3376                'pay_kbn' => 1,
3377                'reference_id' => $userId,
3378                'payment_transaction_password' => $paymentSuccess ? $pt['password'] : '',
3379                'status' => $paymentSuccess ? 1 : '',
3380                'form_type' => Configure::read('payment_credit_receivable'),
3381                'ordd' => $paymentSuccess ? $paymentHash : '',
3382                'amount' => $receivableAmount,
3383                'param1' => $res,
3384                'param2' => $paymentSuccess ? '' : 'error',
3385                'card_company' => Configure::read('card_company.aftee'),
3386                'transaction_code' => $paymentSuccess ? $paymentHash : '',
3387                'currency_id' => Configure::read('default.settlement_currency_id'),
3388                'currency_code' => $currencyCode,
3389                'payment_id' => $paymentPlanId,
3390                'price_id' => $priceId,
3391                'payment_type' => Configure::read('payment_types.payment_receivable'),
3392                'logFileName' => 'debug'
3393            );
3394
3395            // create new payment
3396            $paymentSave = $this->Payment->rawSavePayment($savePaymentArr);
3397        }
3398
3399        // Appreciation payment
3400        if( $appreciationReceivableAmount > 0 ) {
3401            $savePaymentArr = array(
3402                'user_id' => $userId,
3403                'type_id' => 2,
3404                'pay_kbn' => 1,
3405                'reference_id' => $userId,
3406                'payment_transaction_password' => $paymentSuccess ? $pt['password'] : '',
3407                'status' => $paymentSuccess ? 1 : '',
3408                'form_type' => Configure::read('payment_credit_appreciation_receivable'),
3409                'ordd' => $paymentSuccess ? $paymentHash : '',
3410                'amount' => $appreciationReceivableAmount,
3411                'param1' => $res,
3412                'param2' => $paymentSuccess ? '' : 'error',
3413                'card_company' => Configure::read('card_company.aftee'),
3414                'transaction_code' => $paymentSuccess ? $paymentHash : '',
3415                'currency_id' => Configure::read('default.settlement_currency_id'),
3416                'currency_code' => $currencyCode,
3417                'payment_id' => $paymentPlanId,
3418                'price_id' => $priceId,
3419                'payment_type' => Configure::read('payment_types.payment_receivable'),
3420                'logFileName' => 'debug'
3421            );
3422
3423            // create new payment
3424            $paymentSave = $this->Payment->rawSavePayment($savePaymentArr);
3425        }
3426
3427        // Live payment
3428        if( $liveReceivableAmount > 0 ) {
3429            $savePaymentArr = array(
3430                'user_id' => $userId,
3431                'type_id' => 2,
3432                'pay_kbn' => 1,
3433                'reference_id' => $userId,
3434                'payment_transaction_password' => $paymentSuccess ? $pt['password'] : '',
3435                'status' => $paymentSuccess ? 1 : '',
3436                'form_type' => Configure::read('payment_live_lesson_receivable'),
3437                'ordd' => $paymentSuccess ? $paymentHash : '',
3438                'amount' => $liveReceivableAmount,
3439                'param1' => $res,
3440                'param2' => $paymentSuccess ? '' : 'error',
3441                'card_company' => Configure::read('card_company.aftee'),
3442                'transaction_code' => $paymentSuccess ? $paymentHash : '',
3443                'currency_id' => Configure::read('default.settlement_currency_id'),
3444                'currency_code' => $currencyCode,
3445                'payment_id' => $paymentPlanId,
3446                'price_id' => $priceId,
3447                'payment_type' => Configure::read('payment_types.payment_receivable'),
3448                'logFileName' => 'debug'
3449            );
3450
3451            // create new payment
3452            $paymentSave = $this->Payment->rawSavePayment($savePaymentArr);
3453        }        
3454
3455        if ($paymentSave && $paymentSuccess) {
3456
3457            // Update Reservation payment receivables
3458            if( $receivableAmount > 0 ) {
3459                // get payment id
3460                $paymentData = $this->Payment->find('first', array(
3461                    'fields' => array(),
3462                    'conditions' => array(
3463                        'user_id' => $userId,
3464                        'form_type' => Configure::read('payment_credit_receivable'),
3465                        'ordd' => $paymentHash
3466                    ),
3467                    'recursive' => -1
3468                ));
3469
3470                if ($paymentData) {
3471                    $this->loadModel('PaymentReceivable');
3472                    // set payment receivable statuses to 2 - received
3473                    $this->PaymentReceivable->updateReceivableReservationPayment(
3474                        $userId,
3475                        array(
3476                            'status' => 2,
3477                            'payment_id' => $paymentData['Payment']['id'],
3478                            'payment_collection_date' => date("Y-m-d H:i:s"),
3479                            'card_company' => Configure::read('card_company.aftee'),
3480                            'payment_plan_id' => $paymentPlanId,
3481                            'membership_type_index' => $membershipStatusIndex
3482                        ),
3483                        array(
3484                            'PaymentReceivable.user_id' => $userId,
3485                            'PaymentReceivable.status' => 0,
3486                            'PaymentReceivable.payment_element_type' => 1,
3487                            'PaymentReceivable.created <=' => date('Y-m-d H:i:s')
3488                        )
3489                    );
3490                }
3491            }
3492
3493            // Update Appreciation payment receivables
3494            if( $appreciationReceivableAmount > 0 ) {
3495                // get payment id
3496                $paymentData = $this->Payment->find('first', array(
3497                    'fields' => array(),
3498                    'conditions' => array(
3499                        'user_id' => $userId,
3500                        'form_type' => Configure::read('payment_credit_appreciation_receivable'),
3501                        'ordd' => $paymentHash
3502                    ),
3503                    'recursive' => -1
3504                ));
3505
3506                if ($paymentData) {
3507                    $this->loadModel('PaymentReceivable');
3508                    // set payment receivable statuses to 2 - received
3509                    $this->PaymentReceivable->updateReceivableReservationPayment(
3510                        $userId,
3511                        array(
3512                            'status' => 2,
3513                            'payment_id' => $paymentData['Payment']['id'],
3514                            'payment_collection_date' => date("Y-m-d H:i:s"),
3515                            'card_company' => Configure::read('card_company.aftee'),
3516                            'payment_plan_id' => $paymentPlanId,
3517                            'membership_type_index' => $membershipStatusIndex
3518                        ),
3519                        array(
3520                            'PaymentReceivable.user_id' => $userId,
3521                            'PaymentReceivable.status' => 0,
3522                            'PaymentReceivable.payment_element_type' => Configure::read('appreciation_data.payment_element_type'),
3523                            'PaymentReceivable.created <=' => date('Y-m-d H:i:s')
3524                        )
3525                    );
3526                }
3527            }
3528
3529            // Update live payment receivables
3530            if( $liveReceivableAmount > 0 ) {
3531                // get payment id
3532                $paymentData = $this->Payment->find('first', array(
3533                    'fields' => array(),
3534                    'conditions' => array(
3535                        'user_id' => $userId,
3536                        'form_type' => Configure::read('payment_live_lesson_receivable'),
3537                        'ordd' => $paymentHash
3538                    ),
3539                    'recursive' => -1
3540                ));
3541
3542                if ($paymentData) {
3543                    $this->loadModel('PaymentReceivable');
3544                    // set payment receivable statuses to 2 - received
3545                    $this->PaymentReceivable->updateReceivableReservationPayment(
3546                        $userId,
3547                        array(
3548                            'status' => 2,
3549                            'payment_id' => $paymentData['Payment']['id'],
3550                            'payment_collection_date' => date("Y-m-d H:i:s"),
3551                            'card_company' => Configure::read('card_company.aftee'),
3552                            'payment_plan_id' => $paymentPlanId,
3553                            'membership_type_index' => $membershipStatusIndex                            
3554                        ),
3555                        array(
3556                            'PaymentReceivable.user_id' => $userId,
3557                            'PaymentReceivable.status' => 0,
3558                            'PaymentReceivable.payment_element_type' => 3,
3559                            'PaymentReceivable.created <=' => date('Y-m-d H:i:s')
3560                        )
3561                    );
3562                }
3563            }            
3564
3565        }
3566        if( isset($pt['id']) ) {
3567            $ptUpdateParams = array(
3568                'id' => $pt['id'],
3569                'fields' => array(
3570                    'status' => $paymentSuccess ? 1 : 2,
3571                    'response_text' => array('aftee_directPayment_response' => $orderResult)
3572                ),
3573                'logFileName' => 'debug'
3574            );
3575
3576            // update payment transaction
3577            if (!$this->PaymentTransaction->updateAfteePaymentTransaction($ptUpdateParams)) {
3578                $this->log(__METHOD__ . ' Cannot update payment transaction. --> ' . json_encode($ptUpdateParams), 'debug');
3579            }
3580        }
3581
3582        if( isset($apt['id']) ) {
3583            $ptUpdateParams = array(
3584                'id' => $apt['id'],
3585                'fields' => array(
3586                    'status' => $paymentSuccess ? 1 : 2,
3587                    'response_text' => array('aftee_directPayment_response' => $orderResult)
3588                ),
3589                'logFileName' => 'debug'
3590            );
3591            // update payment transaction
3592            if (!$this->PaymentTransaction->updateAfteePaymentTransaction($ptUpdateParams)) {
3593                $this->log(__METHOD__ . ' Cannot update payment transaction. --> ' . json_encode($ptUpdateParams), 'debug');
3594            }
3595        }
3596
3597        if( isset($lpt['id']) ) {
3598            $ptUpdateParams = array(
3599                'id' => $lpt['id'],
3600                'fields' => array(
3601                    'status' => $paymentSuccess ? 1 : 2,
3602                    'response_text' => array('aftee_directPayment_response' => $orderResult)
3603                ),
3604                'logFileName' => 'debug'
3605            );
3606            // update payment transaction
3607            if (!$this->PaymentTransaction->updateAfteePaymentTransaction($ptUpdateParams)) {
3608                $this->log(__METHOD__ . ' Cannot update payment transaction. --> ' . json_encode($ptUpdateParams), 'debug');
3609            }
3610        }        
3611
3612        // log
3613        $this->log(__METHOD__ . "::PaymentReceivable charge on withdrawal. \nData: " . json_encode(array('params' => $params, 'result' => $orderResult)), 'debug');
3614    }
3615
3616    /**
3617     * Aftee Payment method
3618     * Check if aftee should be enabled/disabled in app
3619     */
3620    public function checkAfteeSupported($userData,$pcFlag = false) {
3621        $afteeAppSupportedVersion = Configure::read('aftee_app_version_support');
3622        $appVersion = isset($this->request->query['appVersion']) && !empty($this->request->query['appVersion']) ? $this->request->query['appVersion'] : 0;
3623        $deviceType = isset($this->request->query['deviceType']) && !empty($this->request->query['deviceType']) ? $this->request->query['deviceType'] : 0;
3624
3625        // initial values
3626        $isAfteeUser = isset($this->isAfteeUser) ? $this->isAfteeUser : 0;
3627        $enableAftee = (isset($userData['currency_code']) && $userData['currency_code'] == 'TWD') ? 1: 0;
3628
3629
3630        if (!$pcFlag) {
3631            // validate
3632            if (
3633                (isset($this->localizeIPLang) && !empty($this->localizeIPLang) && $this->localizeIPLang != 'TWD') // allow taiwan IP only
3634                || ($deviceType == "1" && version_compare($appVersion, $afteeAppSupportedVersion[$deviceType], '<')) // check ios app supported version
3635                || (in_array($deviceType, array(2,3)) && version_compare($appVersion, $afteeAppSupportedVersion[$deviceType], '<')) // check android|amazon app supported version
3636            ) {
3637                $enableAftee = 0;
3638                $isAfteeUser = 0;
3639            }
3640        }else{
3641            
3642            // - validate if PC
3643            if (
3644                $appVersion == 0 && 
3645                $deviceType == 0 && 
3646                $this->localizeDir != "zh-tw" 
3647                || 
3648                ($userData['currency_code'] == 'TWD' && $this->localizeDir != "zh-tw" )
3649                ||
3650                ($userData['currency_code'] != 'TWD' && $this->localizeDir != "zh-tw" )
3651                ||
3652                ($userData['currency_code'] != 'TWD' && $this->localizeDir == "zh-tw" )
3653            ) { 
3654                $enableAftee = 0;
3655                $isAfteeUser = 0;
3656            }
3657        }
3658
3659
3660        // set final values
3661        $this->set('isAfteeUser', false);
3662        $this->set('enableAftee', false);
3663    }
3664
3665    public function queryGuideControl()
3666    {
3667        $this->GuideNavigationbarCategory->openDBReplica();
3668        $datas = $this->GuideNavigationbarCategory->find('all', array(
3669            'fields' => array(
3670                'GuideNavigationbarCategory.id',
3671                'GuideNavigationbarCategory.category_name',
3672                'GuideNavigationbarCategory.lang',
3673                'GuideNavigationbarCategory.display_order',
3674                'GuideNavigationbarContent.id',
3675                'GuideNavigationbarContent.content_name',
3676                'GuideNavigationbarContent.url',
3677                'GuideNavigationbarContent.display_order',
3678                'GuideNavigationbarContent.crawl_flg',
3679                '(SELECT GROUP_CONCAT(DISTINCT (unloggedin_flg)) FROM guide_navigationbar_auth_control WHERE guide_navigationbar_content_id = GuideNavigationbarContent.id) as unloggedin_flg',
3680                '(SELECT GROUP_CONCAT(DISTINCT (membership_type)) FROM guide_navigationbar_membership_control WHERE guide_navigationbar_content_id = GuideNavigationbarContent.id) as membership_type',
3681                '(SELECT GROUP_CONCAT(DISTINCT (currency_code)) FROM guide_navigationbar_currency_control WHERE guide_navigationbar_content_id = GuideNavigationbarContent.id) as currency_code',
3682                '(SELECT GROUP_CONCAT(DISTINCT (browser_language)) FROM guide_navigationbar_browser_lang_control WHERE guide_navigationbar_content_id = GuideNavigationbarContent.id) as browser_language'
3683            ),
3684            'joins' => array(
3685                array(
3686                    'type' => 'LEFT',
3687                    'table' => 'guide_navigationbar_content',
3688                    'alias' => 'GuideNavigationbarContent',
3689                    'conditions' => 'GuideNavigationbarCategory.id = GuideNavigationbarContent.category_id'
3690                )
3691            ),
3692            'conditions' => array(
3693                'GuideNavigationbarCategory.device_type' => 1,
3694                'GuideNavigationbarContent.device_type' => 1
3695            ),
3696            'group' => 'GuideNavigationbarContent.id',
3697            'order' => array(
3698                'GuideNavigationbarCategory.display_order ASC',
3699                'GuideNavigationbarContent.display_order ASC'
3700            ),
3701            'recursive' => -1
3702        ));
3703        $this->GuideNavigationbarCategory->closeDBReplica();
3704
3705        $guideControlCat = array();
3706        if ($datas) {
3707            foreach ($datas as $key=>$data) {
3708                $category_id = $data['GuideNavigationbarCategory']['id'];
3709                $category_name = $data['GuideNavigationbarCategory']['category_name'];
3710
3711                $guideControlCat[$category_id]['category_name'] = $category_name;
3712                $guideControlCat[$category_id]['guide_navigation_bar_content'][$key]['content'] = $data['GuideNavigationbarContent'];
3713                $guideControlCat[$category_id]['guide_navigation_bar_content'][$key]['control'] = $data['0'];
3714            }
3715
3716            $redis = new myRedis();
3717            $redisKey = "dynamic_global_guide_control";
3718
3719            $guideControlCached = $redis->get($redisKey);
3720
3721            if (!$guideControlCached){
3722                $redis->set(array(
3723                    'key' => $redisKey,
3724                    'value' => json_encode($guideControlCat)
3725                ));
3726            }
3727        }
3728
3729        $this->set('GuideNavigationbarCategory', $guideControlCat);
3730    }
3731
3732    // 
3733    public function queryLineHoverControl(){
3734
3735        $returnData = array();
3736
3737        $this->RyugakuSchoolLineSetting->openDBReplica();
3738        $datas = $this->RyugakuSchoolLineSetting->find('all',array(
3739            'fields' => array(
3740                'RyugakuSchoolLineSetting.id',
3741                'RyugakuSchoolLineSetting.line_title',
3742                'RyugakuSchoolLineSetting.line_description',
3743                'RyugakuSchoolLineSetting.line_hover_location_url'
3744            ),
3745            'conditions' => array(),
3746            'recursive' => -1
3747        ));
3748        $this->RyugakuSchoolLineSetting->closeDBReplica();
3749
3750        if ($datas) {
3751            foreach ($datas as $key => $hover) {
3752
3753                $hover=$hover['RyugakuSchoolLineSetting'];
3754
3755                $returnData[] = array(
3756                    'title' => $hover['line_title'],
3757                    'description' => $hover['line_description'],
3758                    'url' => $hover['line_hover_location_url']
3759                );
3760            }
3761        }
3762
3763        $this->set('lineHoverGuide', $returnData);
3764    }
3765
3766    /**
3767     * NJ-27594
3768     * @param String $version - app version,
3769     * @param Int $device_type - 1 - iOS, 2 Android
3770     *
3771     * @return void
3772     */
3773    private function NCPlusPositionUrlScheme($version, $device_type) {
3774        $supportedVersion = Configure::read('nc_plus_positions_url_scheme')[$device_type];
3775        if( version_compare($version, $supportedVersion, '>=')) {
3776            $this->set('position_url_scheme_support', 1);    
3777        } 
3778    }
3779
3780    // NJ-18780 : light plan 
3781    public function checkLitePlanSupported($userData = array(),$pcFlag = false,$page = null){
3782        $enableLitePlan = 0;
3783        $isLitePlanUser = 0;
3784            
3785        $litePlanAppSupportedVersion = Configure::read('lite_plan_app_version_support');
3786        $appVersion = isset($this->request->query['appVersion']) && !empty($this->request->query['appVersion']) ? $this->request->query['appVersion'] : 0;
3787        $deviceType = isset($this->request->query['deviceType']) && !empty($this->request->query['deviceType']) ? $this->request->query['deviceType'] : 0;
3788    
3789        if ($userData) {
3790                // added localize dir overriding to properly get the lite plan data even if the user account is in different language site but currency code is JPY.
3791                $localizeDir = (isset($userData['override_localize_dir'])) ? $userData['override_localize_dir'] : $this->localizeDir;
3792                $setEnableLitePlan = UserTable::checkLitePlanSupported($userData,$pcFlag,$appVersion,$deviceType,$localizeDir,$this->localizeIPLang);
3793    
3794                $enableLitePlan = $setEnableLitePlan['enableLitePlan'];
3795                $isLitePlanUser = $setEnableLitePlan['isLitePlanUser'];
3796    
3797                // - prem complimentary that wan't to change to plan using credit_charge
3798                if (
3799                    isset($userData['payment_plan_id']) && 
3800                    $userData['payment_plan_id'] &&
3801                    $userData['payment_plan_id'] == Configure::read('payment_plans.complimentary_plan') &&
3802                    isset($userData['complimentary_code']) &&
3803                    $userData['complimentary_code'] &&
3804                    in_array($page, array('credit_charge'))
3805                ) {
3806                    # allow check enable lite plan
3807                    if ($this->localizeDir == 'ja') {
3808                        $enableLitePlan = (isset($userData['currency_code']) && $userData['currency_code'] == 'JPY') ? 1: 0;
3809                    } else {
3810                        $enableLitePlan = 0;
3811                    }
3812                }
3813    
3814                if (!empty($page) && !in_array($page, array('credit_charge'))) { 
3815                    $enableLitePlan = 0;
3816                    $isLitePlanUser = 0;
3817
3818                    if ($this->localizeDir == 'ja') {
3819                        $enableLitePlan = 1;
3820                    }
3821                }
3822                
3823                // - allow for corporate charge page 
3824                if (
3825                    isset($userData['corporate_id']) && 
3826                    $userData['corporate_id'] && 
3827                    isset($userData['payment_plan_id']) && 
3828                    $userData['payment_plan_id'] && 
3829                    in_array($page, array('credit_charge'))                    
3830                ) {
3831                    # allow check enable lite plan
3832                    if ($this->localizeDir == 'ja') {
3833                        $enableLitePlan = (isset($userData['currency_code']) && $userData['currency_code'] == 'JPY') ? 1: 0;
3834                    } else {
3835                        $enableLitePlan = 0;
3836                    }
3837                }
3838        }
3839    
3840        // set final values
3841        $this->set('enableLitePlan',$enableLitePlan);
3842        $this->set('isLitePlanUser',$isLitePlanUser);
3843    
3844        // - set return to view 
3845        return array('enableLitePlan' => $enableLitePlan,'isLitePlanUser' => $isLitePlanUser);
3846    
3847    }
3848
3849    /**
3850     * NJ-27262: Resets Users Preset when 
3851     * changed to Chocotto Camp
3852     */
3853    public function resetPresetTextbook($params = []) {
3854        $this->autoRender = false;
3855        $this->layout = false;
3856
3857        if(!$params) {
3858            return;
3859        }
3860
3861        $connect_id = isset($params['connect_id']) ? $params['connect_id'] : Configure::read('textbook_default.chocotto_textbook_connect_id');
3862        
3863        myTools::initializeApiTunnel(array('TextbookUpdatePresetController'));
3864        
3865        $preset = new TextbookUpdatePresetController();
3866
3867        $user = $this->User->find('first', array(
3868            'fields' => array(
3869                'User.id',
3870                'User.api_token',
3871            ),
3872            'conditions' => array(
3873                'User.id' => $params['user_id']
3874            )
3875        ));
3876        
3877        if($user) {
3878            $apiParams = array(
3879                'connect_id' => $connect_id,
3880                'users_api_token' => $user['User']['api_token'],
3881                'nc_terminal_type' => Configure::read('nc_terminal_type.pc')
3882            );
3883    
3884            $preset->params = $apiParams;
3885            $preset->index();
3886        }
3887        
3888    }
3889    
3890    public function setPaypalUser($user = array()) {
3891        
3892        // Check if paypal user
3893        $isPaypalUser = (isset($user['paypal_payer_id']) && isset($user['paypal_payer_email']) && $user['paypal_payer_email']) ? true : false;
3894        $paypal_icon = "/images/pay/Icon_paypal.png";
3895        $paypal_payer_email = (isset($user['paypal_payer_email']) && $user['paypal_payer_email']) ? $user['paypal_payer_email'] : null;
3896
3897        $this->set('isPaypalUser', $isPaypalUser);
3898        $this->set('paypal_icon', $paypal_icon);
3899        $this->set('paypal_payer_email', $paypal_payer_email);
3900    }
3901
3902
3903    /**
3904     * Stripe Payment method
3905     * Check if stripe apple/google pay should be enabled/disabled in app
3906     */
3907    public function checkStripeSupported($userData,$pcFlag = false) {
3908        $stripeAppSupportedVersion = Configure::read('stripe_app_version_support');
3909        $stripeAppSupportedCurrencies = Configure::read('stripe.allowed_currencies');
3910        $appVersion = isset($this->request->query['appVersion']) && !empty($this->request->query['appVersion']) ? $this->request->query['appVersion'] : 0;
3911        $deviceType = isset($this->request->query['deviceType']) && !empty($this->request->query['deviceType']) ? $this->request->query['deviceType'] : 0;
3912        $device = myTools::getDevice();
3913        $userCurrecy = isset($userData['currency_code']) ? $userData['currency_code'] : '';
3914        if(isset($this->mobAppUserData) && $this->mobAppUserData['User']['currency_code']) {
3915            $userCurrecy = $this->mobAppUserData['User']['currency_code'];
3916        } else {
3917            $userCurrecy = (
3918                isset($this->sharedUserData) &&
3919                is_array($this->sharedUserData) &&
3920                isset($this->sharedUserData['User']) &&
3921                is_array($this->sharedUserData['User']) &&
3922                isset($this->sharedUserData['User']['currency_code']) &&
3923                $this->sharedUserData['User']['currency_code']
3924            )
3925                ? $this->sharedUserData['User']['currency_code']
3926                : Configure::read('default.user_currency');
3927        }
3928
3929        // initial values
3930        $isStripeUser = isset($this->isStripeUser) ? $this->isStripeUser : false;
3931        $enableStripe = false;
3932        $stripePaymentType = $device == 3 ? 'apple' : 'google';
3933        $stripeChangePaymentMethod = false;
3934
3935        if (
3936            $isStripeUser ||
3937            (
3938                ($device == "3" && version_compare($appVersion, $stripeAppSupportedVersion[1], '>=') && in_array($userCurrecy, $stripeAppSupportedCurrencies['apple'])) // ios app supported version
3939                || (in_array($device, array(2,4)) && version_compare($appVersion, $stripeAppSupportedVersion[2], '>=') && in_array($userCurrecy, $stripeAppSupportedCurrencies['google'])) // android|amazon app supported version
3940            )
3941        ) {
3942            $enableStripe = true;
3943        }
3944
3945        // Phase 1: Disbale Stripe in some payment pages
3946        if (isset($this->request->params['action']) && !in_array($this->request->params['action'], array('credit', 'creditform', 'native_plan', 'wp_credit', 'wp_creditform', 'mobapp_credit_change_form', 'mobapp_wp_credit_change_form', 'mobapp_wp_credit_retry', 'mobapp_wp_credit_retry_form', 'mobapp_wp_credit_retry_confirm', 'mobapp_credit_retry', 'mobapp_credit_retry_form', 'mobapp_credit_retry_complete'))) {
3947            $enableStripe = false;
3948        }
3949
3950        // Change Payment method: enable for Stripe users only
3951        if (
3952            isset($this->request->params['action']) && in_array($this->request->params['action'], array('mobapp_credit_change_form', 'mobapp_wp_credit_change_form'))
3953        ) {
3954            $stripeChangePaymentMethod = true;
3955            if (!$isStripeUser) {
3956                $enableStripe = false;
3957            }
3958            
3959        }
3960
3961        // Failed Payment Retry: enable for Stripe users only
3962        if (
3963            (isset($this->request->params['action']) && in_array($this->request->params['action'], array('mobapp_wp_credit_retry', 'mobapp_wp_credit_retry_form', 'mobapp_wp_credit_retry_confirm', 'mobapp_credit_retry', 'mobapp_credit_retry_form', 'mobapp_credit_retry_complete')))
3964            && !$isStripeUser
3965        ) {
3966            $enableStripe = false;        
3967        }
3968
3969        // Disable Stripe if KRW and GPay
3970        if ($isStripeUser && $userCurrecy == 'KRW' && $stripePaymentType != 'apple') {
3971            $enableStripe = false;
3972        }
3973
3974        // set final values
3975        $this->set('isStripeUser', $isStripeUser);
3976        $this->set('enableStripe', $enableStripe);
3977        $this->set('stripePaymentType', $stripePaymentType);
3978        $this->set('stripeChangePaymentMethod', $stripeChangePaymentMethod);
3979    }
3980    /**
3981     * ~NJ-29078 - process child receivable payment 
3982     * @param array $familyArr, array $parentArr
3983     */
3984    public function processChildReceivablePayment($familyArr = [], $parentArr = [])
3985    {
3986        $logFileName = 'family_plan';
3987        $curlPayment = "";
3988
3989        if (!$pt = $this->Payment->setUpWithdrawTransaction($familyArr, $logFileName)) {
3990            return false;
3991        }
3992
3993        // ~if zero receivable just return success
3994        if (isset($pt['totalAmount']) && $pt['totalAmount'] == 0) {
3995            $this->log(__METHOD__ . ' No receivable to process' . json_encode($pt), $logFileName);
3996            $curlPayment = "success_order";
3997            return $curlPayment;
3998        }
3999
4000        $familyObj = new UserTable($familyArr);
4001        $parentObj = new UserTable($parentArr);
4002
4003        if ($parentObj->card_company == Configure::read('card_company.zeus')) {
4004            $data = array(
4005                'clientIp' => PaymentTable::getClientIpByCompanyId($parentObj->card_company),
4006                'email' => $parentObj->email,
4007                'sendId' => $parentObj->id,
4008                'money' => $pt['totalAmount'],
4009                'paymentHash' => $pt['payment_hash']
4010            );
4011            // ~process
4012            $curlPayment = $this->ZCharge->charge_with_regsterd_card(json_encode($data));
4013            $curlPayment = PaymentTable::checkPaymentResult($curlPayment);
4014        } else if ($parentObj->card_company == Configure::read('card_company.worldpay')) {
4015            $paymentMethodType = myTools::getWPPaymentMethodType($parentObj->card_brand, 'payment');
4016            $merchantCode = myTools::getWPMerchantCode($paymentMethodType);
4017            $paymentHash = $pt['payment_hash'];
4018            $paymentMethod = explode('_', $paymentMethodType);
4019            $paymentMethod = isset($paymentMethod[0]) ? $paymentMethod[0] : null;
4020            $currencyExponents = Configure::read('worldpay.currency_exponents');
4021            $exponent = $currencyExponents[$parentObj->currency_code];
4022            // get amount with checking currency exponent
4023            $amountArr = myTools::wpGetAmount($exponent, $pt['totalAmount']);
4024            $wpAmount = $amountArr['wpAmount'];
4025
4026            $decodePaymentParams = json_decode($pt['payment_params']);
4027            $paymentFormType = $decodePaymentParams->formType;
4028
4029            $wpParams = array(
4030                'merchantCode' => $merchantCode,
4031                'orderCode' => $paymentHash,
4032                'description' => 'Child Withdrawal Receivables',
4033                'currencyCode' => $parentObj->currency_code,
4034                'exponent' => $exponent,
4035                'amount' => $wpAmount,
4036                'cardToken' => $parentObj->card_token,
4037                'email' => $parentObj->email,
4038                'authenticatedShopperId' => $parentObj->id,
4039                'xmlName' => 'direct_payment_with_token',
4040                'shopperIpAddress' => $_SERVER["REMOTE_ADDR"],
4041                'wpTransactionIdentifier' => $parentObj->wp_transaction_identifier,
4042                'paymentMethod' => $paymentMethod
4043            );
4044
4045            $updateData = array(
4046                'id' => $pt['id'],
4047                'fields' => array('payment_params' => $wpParams)
4048            );
4049
4050            if (!$this->PaymentTransaction->updateWPPaymentTransaction($updateData)) {
4051                $this->log(__METHOD__ . ' Failed to update payment transaction' . json_encode($updateData), $logFileName);
4052            } else {
4053                if (!$pt = $this->PaymentTransaction->getWPPaymentTransaction($paymentHash)) {
4054                    return false;
4055                }
4056            }
4057
4058            // ~process
4059            $res = wpPaymentService::directPayment($wpParams);
4060
4061            $updateData = array(
4062                'id' => $pt['id'],
4063                'fields' => array('response_text' => array('directPayment_response' => $res))
4064            );
4065
4066            if (!$this->PaymentTransaction->updateWPPaymentTransaction($updateData)) {
4067                $this->log(__METHOD__ . ' Failed to update payment transaction' . json_encode($updateData), $logFileName);
4068            }
4069
4070            if (!myTools::checkIfWPPaymentResponseIsAuthorised($res)) {
4071                $curlPayment = "";
4072                $this->log(__METHOD__ . ' Not authorised payment worldpay' . (isset($familyObj->id) ? $familyObj->id : ''), $logFileName);
4073            } else {
4074                $curlPayment = "success_order";
4075            }
4076        } else if ($parentObj->card_company == Configure::read('card_company.aftee')) {
4077            $paymentMethodType = myTools::getWPPaymentMethodType($parentObj->card_brand, 'payment');
4078            $merchantCode = myTools::getWPMerchantCode($paymentMethodType);
4079            $paymentHash = $pt['payment_hash'];
4080            $paymentMethod = explode('_', $paymentMethodType);
4081            $paymentMethod = isset($paymentMethod[0]) ? $paymentMethod[0] : null;
4082            $decodePaymentParams = json_decode($pt['payment_params']);
4083            $paymentFormType = $decodePaymentParams->formType;
4084
4085            $afteeParams = array(
4086                'merchantCode' => $merchantCode,
4087                'orderCode' => $paymentHash,
4088                'description' => 'Family Plan Registration',
4089                'currencyCode' => $parentObj->currency_code,
4090                'amount' => $pt['totalAmount'],
4091                'cardToken' => $parentObj->card_token,
4092                'email' => $parentObj->email,
4093                'authenticatedShopperId' => $parentObj->id,
4094                'shopperIpAddress' => $_SERVER["REMOTE_ADDR"],
4095                'afteeTransactionIdentifier' => $parentObj->aftee_transaction_identifier,
4096                'paymentMethod' => $paymentMethod
4097            );
4098
4099            $updateData = array(
4100                'id' => $pt['id'],
4101                'fields' => array('payment_params' => $afteeParams)
4102            );
4103
4104            if (!$this->PaymentTransaction->updateAfteePaymentTransaction($updateData)) {
4105                $this->log(__METHOD__ . ' Failed to update payment transaction' . json_encode($updateData), $logFileName);
4106            } else {
4107                if (!$pt = $this->PaymentTransaction->getAfteePaymentTransaction($paymentHash)) {
4108                    return false;
4109                }
4110            }
4111
4112            // ~process
4113            $afteeParams = array(
4114                'parent' =>  $parentObj,
4115                'child' =>  $familyObj,
4116                'paymentTransaction' => $pt,
4117                'appreciationFlg' => $familyObj->allow_appreciation_flg,
4118                'tipAmount' => myTools::stringToFloat($familyObj->tip_max_amount)
4119            );
4120
4121            $curlPayment = $this->processChildAfteePayment($afteeParams);
4122        } elseif ($parentObj->card_company == Configure::read('card_company.paypal')) {
4123            $paypalParams = array(
4124                'parent' => $parentObj,
4125                'child' => $familyObj,
4126                'paymentTransaction' => $pt,
4127                'memberStatus' => 'exist'
4128            );
4129
4130            $curlPayment = $this->processChildPaypalPayment($paypalParams);
4131        } else if ($parentObj->card_company == Configure::read('card_company.stripe.apple') || $parentObj->card_company == Configure::read('card_company.stripe.google')){
4132            if (!class_exists('Stripe')) {
4133                App::import('Lib', 'Stripe');
4134            }
4135
4136            $data = array(
4137                'customerId' => $parentObj->stripe_customer_id,
4138                'amount' => $pt['totalAmount'],
4139                'currency' => $parentObj->currency_code,
4140                'paymentMethodID' => $parentObj->stripe_payment_identifier,
4141                'description' => 'Family Plan Receivable Payment',
4142                'sendpoint' => $pt['payment_hash'],
4143                'sendid' => $parentObj->id,
4144                'card_company' => $parentObj->card_company
4145            );
4146            
4147            $stripe = new Stripe();
4148            $curlPayment = $stripe->directPayment($data);    
4149            $curlPayment = myTools::checkStripePaymentResponse($curlPayment);
4150
4151        }
4152
4153        return $curlPayment;
4154    }
4155
4156    // ~NJ-29078 - Withdraw Paypal Process Payment
4157    private function processChildPaypalPayment($params = array())
4158    {
4159        $logFileName = 'family_plan';
4160        if (
4161            !isset($params['child']) ||
4162            !isset($params['parent']) ||
4163            !isset($params['paymentTransaction'])
4164        ) {
4165            $this->log('__METHOD__' . ' missing parameter(s). --> ' . json_encode($params), $logFileName);
4166            return false;
4167        }
4168
4169        // ~check for family parent 
4170        $child = $params['child'];
4171        $parent = $params['parent'];
4172        $pt = $params['paymentTransaction'];
4173        $memberStatus = $params['memberStatus'];
4174
4175        $paymentHash = $pt['payment_hash'];
4176        $ptPassword = $pt['password'];
4177        $ptParams = json_decode($pt['payment_params'], true);
4178
4179        $formType = $ptParams['formType'];
4180        $currencyCode = $ptParams['currencyCode'];
4181        $paymentPlanId = $ptParams['paymentPlanId'];
4182        $priceId = $ptParams['priceId'];
4183        $paymentType = Configure::read('payment_types.payment_receivable');
4184        $platform = $ptParams['platform'];
4185
4186        $membershipStatusIndex = UserTable::getStudentMembershipStatus($child->id);
4187        $currencyId = Configure::read('default.settlement_currency_id'); // set currency id to jpy
4188        $cardCompany = Configure::read('card_company.paypal');
4189        $dateTimeNow = date('Y-m-d H:i:s');
4190
4191        $reservationReceivableAmount = isset($ptParams['reservationReceivableAmount']) ? $ptParams['reservationReceivableAmount'] : 0;
4192        $appreciationReceivableAmount = isset($ptParams['appreciationReceivableAmount']) ? $ptParams['appreciationReceivableAmount'] : 0;
4193        $liveReceivableAmount = isset($ptParams['liveReceivableAmount']) ? $ptParams['liveReceivableAmount'] : 0;
4194
4195
4196        if (!class_exists('PayPal')) {
4197            App::import('Lib', 'PayPal');
4198        }
4199
4200        $PayPal = new PayPal();
4201        $accessTokenData = $PayPal->getAccessToken();
4202
4203        $totalAmount = (int) ($reservationReceivableAmount + $appreciationReceivableAmount + $liveReceivableAmount);
4204
4205        $paypalParams = array(
4206            'ptId' => $pt['id'],
4207            'paypalData' => array('accessTokenData' => $accessTokenData),
4208            'userId' => isset($child->id) ? $child->id : (method_exists($child, 'getId') ? $child->getId() : null),
4209            'money' => $totalAmount,
4210            'formType' => $formType,
4211            'priceId' => $priceId,
4212            'paymentId' => $paymentPlanId,
4213            'paymentType' => $paymentType
4214        );
4215
4216        $receivables = [
4217            'payment_credit_receivable' => $reservationReceivableAmount,
4218            'payment_credit_appreciation_receivable' => $appreciationReceivableAmount,
4219            'payment_live_lesson_receivable' => $liveReceivableAmount
4220        ];
4221
4222        // break if error
4223        if (!isset($accessTokenData['access_token'])) {
4224            $this->log(__METHOD__ . ' paypal error --> ' . json_encode($accessTokenData) . ' --> ' . json_encode($params), $logFileName);
4225            $this->savePaypalFailedSettlement($receivables, $paypalParams);
4226            return;
4227        }
4228
4229        $createOrderParams = array(
4230            'accessToken' => $accessTokenData['access_token'],
4231            'paypalRequestId' => $pt['id'],
4232            'intent' => 'CAPTURE',
4233            'paymentHash' => $paymentHash,
4234            'userId' => $parent->id ?? null,
4235            'currencyCode' => $currencyCode,
4236            'amount' => $totalAmount,
4237            'billingAgreementId' => $parent->paypal_billing_agreement_id ?? null
4238        );
4239
4240        // add mock application code
4241        if (isset($request['mockResponse'])) {
4242            $createOrderParams['mockResponse'] = $request['mockResponse'];
4243        }
4244
4245        $curlPayment = $PayPal->createOrder($createOrderParams);
4246        $paypalParams['paypalData']['createOrder'] = $curlPayment;
4247        $paymentSuccess = isset($curlPayment['status']) && $curlPayment['status'] == 'COMPLETED' ? true : false;
4248
4249        if (!$paymentSuccess) {
4250            $this->log(__METHOD__ . ' paypal error --> ' . json_encode($curlPayment) . ' --> ' . json_encode($params), $logFileName);
4251            $this->savePaypalFailedSettlement($receivables, $paypalParams);
4252            return;
4253        }
4254
4255        // create payment
4256        $savePaymentArr = array(
4257            'user_id' => $child->id,
4258            'amount' => $totalAmount,
4259            'status' => 1,
4260            'reference_id' => $child->id,
4261            'payment_transaction_password' => $ptPassword,
4262            'card_company' => $cardCompany,
4263            'param1' => json_encode($paypalParams),
4264            'form_type' => $formType,
4265            'ordd' => $paymentHash,
4266            'transaction_code' => $paymentHash,
4267            'currency_id' => $currencyId,
4268            'currency_code' => $currencyCode,
4269            'payment_id' => $paymentPlanId,
4270            'price_id' => $priceId,
4271            'payment_type' => $paymentType
4272        );
4273
4274        $this->Payment->clear();
4275        $this->Payment->create();
4276        $this->Payment->set($savePaymentArr);
4277        $this->Payment->validate = array();
4278
4279        // update/add user`s settlement amount
4280        $this->User->updateUserPayments($savePaymentArr);
4281
4282        // set payment_id
4283        $paymentSaveID = $this->Payment->id;
4284        $data = array('payment_id' => $paymentSaveID);
4285        $paymentType = Configure::read('payment_types.payment_receivable');
4286
4287        // reservation receivable
4288        if ($reservationReceivableAmount > 0) {
4289            $savePaymentArr = array(
4290                'user_id' => $child->id,
4291                'amount' => $reservationReceivableAmount,
4292                'status' => 1,
4293                'type_id' => 1,
4294                'reference_id' => $child->id,
4295                'card_company' => $cardCompany,
4296                'param1' => json_encode($data),
4297                'form_type' => Configure::read('payment_credit_receivable'),
4298                'ordd' => $paymentHash,
4299                'transaction_code' => $paymentHash,
4300                'currency_id' => $currencyId,
4301                'currency_code' => $currencyCode,
4302                'payment_id' => $paymentPlanId,
4303                'price_id' => $priceId,
4304                'payment_type' => $paymentType
4305            );
4306
4307            // create new payment for reservation receivable
4308            $this->Payment->clear();
4309            $this->Payment->create();
4310            $this->Payment->set($savePaymentArr);
4311            if (!$this->Payment->save()) {
4312                $this->log(__METHOD__ . ' Failed to save payment data for reservation receivable.' . json_encode($savePaymentArr), $logFileName);
4313                return;
4314            }
4315
4316            // set payment_id
4317            $rrPaymentID = $this->Payment->id;
4318
4319            //update/add user`s settlement amount
4320            $this->User->updateUserPayments($savePaymentArr);
4321
4322            // set payment receivable statuses to 2 - received
4323            $this->PaymentReceivable->updateReceivableReservationPayment(
4324                $child->id,
4325                array(
4326                    'status' => 2,
4327                    'payment_id' => $rrPaymentID,
4328                    'payment_collection_date' => $dateTimeNow,
4329                    'card_company' => $cardCompany,
4330                    'payment_plan_id' => $paymentPlanId,
4331                    'membership_type_index' => $membershipStatusIndex
4332                ),
4333                array(
4334                    'PaymentReceivable.user_id' => $child->id,
4335                    'PaymentReceivable.status' => 0,
4336                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.reservation'),
4337                    'PaymentReceivable.created <=' => $dateTimeNow
4338                )
4339            );
4340        }
4341
4342        // appreciation receivable
4343        if ($appreciationReceivableAmount > 0) {
4344            $savePaymentArr = array(
4345                'user_id' => $child->id,
4346                'amount' => $appreciationReceivableAmount,
4347                'status' => 1,
4348                'type_id' => 1,
4349                'reference_id' => $child->id,
4350                'card_company' => $cardCompany,
4351                'param1' => json_encode($data),
4352                'form_type' => Configure::read('payment_credit_appreciation_receivable'),
4353                'ordd' => $paymentHash,
4354                'transaction_code' => $paymentHash,
4355                'currency_id' => $currencyId,
4356                'currency_code' => $currencyCode,
4357                'payment_id' => $paymentPlanId,
4358                'price_id' => $priceId,
4359                'payment_type' => $paymentType
4360            );
4361
4362            // create new payment for appreciation receivable
4363            $this->Payment->clear();
4364            $this->Payment->create();
4365            $this->Payment->set($savePaymentArr);
4366            if (!$this->Payment->save()) {
4367                $this->log(__METHOD__ . ' Failed to save payment data for appreciation receivable.' . json_encode($savePaymentArr), $logFileName);
4368                return;
4369            }
4370
4371            // set payment_id
4372            $arPaymentID = $this->Payment->id;
4373
4374            //update/add user`s settlement amount
4375            $this->User->updateUserPayments($savePaymentArr);
4376
4377            // set payment receivable statuses to 2 - received
4378            $this->PaymentReceivable->updateReceivableReservationPayment(
4379                $child->id,
4380                array(
4381                    'status' => 2,
4382                    'payment_id' => $arPaymentID,
4383                    'payment_collection_date' => $dateTimeNow,
4384                    'card_company' => $cardCompany,
4385                    'payment_plan_id' => $paymentPlanId,
4386                    'membership_type_index' => $membershipStatusIndex
4387                ),
4388                array(
4389                    'PaymentReceivable.user_id' => $child->id,
4390                    'PaymentReceivable.status' => 0,
4391                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.appreciation'),
4392                    'PaymentReceivable.created <=' => $dateTimeNow
4393                )
4394            );
4395        }
4396
4397        // live receivable
4398        if ($liveReceivableAmount > 0) {
4399            $savePaymentArr = array(
4400                'user_id' => $child->id,
4401                'amount' => $liveReceivableAmount,
4402                'status' => 1,
4403                'type_id' => 1,
4404                'reference_id' => $child->id,
4405                'card_company' => $cardCompany,
4406                'param1' => json_encode($data),
4407                'form_type' => Configure::read('payment_live_lesson_receivable'),
4408                'ordd' => $paymentHash,
4409                'transaction_code' => $paymentHash,
4410                'currency_id' => $currencyId,
4411                'currency_code' => $currencyCode,
4412                'payment_id' => $paymentPlanId,
4413                'price_id' => $priceId,
4414                'payment_type' => $paymentType
4415            );
4416
4417            // create new payment for live receivable
4418            $this->Payment->clear();
4419            $this->Payment->create();
4420            $this->Payment->set($savePaymentArr);
4421            if (!$this->Payment->save()) {
4422                $this->log(__METHOD__ . ' Failed to save payment data for live receivable.' . json_encode($savePaymentArr), $logFileName);
4423                return;
4424            }
4425
4426            // set payment_id
4427            $lrPaymentID = $this->Payment->id;
4428
4429            //update/add user`s settlement amount
4430            $this->User->updateUserPayments($savePaymentArr);
4431
4432            // set payment receivable statuses to 2 - received
4433            $this->PaymentReceivable->updateReceivableReservationPayment(
4434                $child->id,
4435                array(
4436                    'status' => 2,
4437                    'payment_id' => $lrPaymentID,
4438                    'payment_collection_date' => $dateTimeNow,
4439                    'card_company' => $cardCompany,
4440                    'payment_plan_id' => $paymentPlanId,
4441                    'membership_type_index' => $membershipStatusIndex
4442                ),
4443                array(
4444                    'PaymentReceivable.user_id' => $child->id,
4445                    'PaymentReceivable.status' => 0,
4446                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.live'),
4447                    'PaymentReceivable.created <=' => $dateTimeNow
4448                )
4449            );
4450        }
4451
4452        $fields = array('status' => 1);
4453        if (isset($paypalParams)) {
4454            $fields['response_text'] = array('paypal_response' => $paypalParams);
4455        }
4456
4457        // update payment transaction
4458        $this->PaymentTransaction->updateWPPaymentTransaction(array('id' => $ptId ?? null, 'fields' => $fields));
4459
4460        return 'success_order';
4461    }
4462
4463    // ~NJ-29078 - Withdraw Aftee Process Payment
4464    private function processChildAfteePayment($params = array())
4465    {
4466        $logFileName = 'family_plan';
4467        if (
4468            !isset($params['child']) ||
4469            !isset($params['parent']) ||
4470            !isset($params['paymentTransaction'])
4471        ) {
4472            $this->log('__METHOD__' . ' missing parameter(s). --> ' . json_encode($params), $logFileName);
4473            return false;
4474        }
4475
4476        $parent = $params['parent'];
4477        $child = $params['child'];
4478        $pt = $params['paymentTransaction'];
4479
4480        $ptId = $pt['id'];
4481        $ptPassword = $pt['password'] ?? '';
4482        $ptParams = json_decode($pt['payment_params'], true);
4483
4484        $formType = $ptParams['formType'];
4485        $currencyCode = $ptParams['currencyCode'] ?? null;
4486        $paymentPlanId = $ptParams['paymentPlanId'] ?? null;
4487        $priceId = $ptParams['priceId'] ?? null;
4488        $paymentType = $ptParams['paymentType'] ?? null;
4489        $platform = $ptParams['platform'] ?? null;
4490        $paymentHash = $ptParams['orderCode'] ?? null;
4491        $afteeTransactionIdentifier = $ptParams['afteeTransactionIdentifier'] ?? null;
4492
4493        $membershipStatusIndex = UserTable::getStudentMembershipStatus(isset($child->id) ? $child->id : (method_exists($child, 'getId') ? $child->getId() : null));
4494        $currencyId = Configure::read('default.settlement_currency_id'); // set currency id to jpy
4495        $cardCompany = Configure::read('card_company.aftee');
4496        $dateTimeNow = date('Y-m-d H:i:s');
4497
4498        $appreciationFlg = 0;
4499        // $this->log(__METHOD__ . ' aftee debug --> ' . json_encode($params), $logFileName);
4500        // $this->log(__METHOD__ . ' aftee debug --> ' . json_encode($pt), $logFileName);
4501        // $this->log(__METHOD__ . ' aftee debug --> ' . $paymentHash, $logFileName);
4502
4503        // initial aftee amount
4504        $totalAmount = (int)($ptParams['paymentAmount'] ?? 0);
4505        if ($totalAmount > 0) {
4506            if (isset($parent->aftee_transaction_identifier) && !empty($parent->aftee_transaction_identifier)) {
4507                $related_id = $parent->aftee_transaction_identifier;
4508            } else {
4509                $related_id = $afteeTransactionIdentifier;
4510            }
4511
4512            // load PayPal class
4513            if (!class_exists('AfteePaymentService')) {
4514                App::import('Lib', 'AfteePaymentService');
4515            }
4516
4517            $afteeChecksumData = array(
4518                'shopItemId' => "AFTEE" . $formType,
4519                'itemName' => 'FamilyPlanRegistration',
4520                'itemPrice' => $totalAmount,
4521                'itemCount' => 1,
4522                'customerPhoneNumber' => $parent->phone_number,
4523                'customerEmail' => $parent->email,
4524                'shopTransactionNo' => $paymentHash,
4525                'userID' => $parent->id
4526            );
4527            $afteeService = new AfteePaymentService();
4528            $checksum = $afteeService->generateChecksum($afteeChecksumData, false);
4529
4530
4531            $afteeData = array(
4532                'authentication_token' => $parent->card_token,
4533                'related_id' => $related_id,
4534                'checksum' => $checksum['checksum'],
4535                'shop_transaction_no' => $paymentHash,
4536                'transaction_options' => array(1)
4537            );
4538
4539            $afteePaymentData = array_merge($afteeData, $checksum['settlementData']);
4540
4541            // process Aftee direct payment
4542            $res = $afteeService->directPayment($afteePaymentData);
4543            $checkRes = json_decode($res, true);
4544            // $this->log(__METHOD__ . ' aftee --> ' . json_encode($afteePaymentData) . ' --> ' . json_encode($checkRes), $logFileName);
4545
4546            if (isset($checkRes['object']) && $checkRes['object'] == 'transaction') {
4547                $paymentSuccess = true;
4548            } else if (!array_key_exists("object", $checkRes) || (isset($checkRes['object']) && $checkRes['object'] == 'error')) {
4549                $paymentSuccess = false;
4550            }
4551        } else {
4552            // zero payment
4553            $checkRes = array('aftee zero payment --> family plan registration');
4554            $paymentSuccess = true;
4555        }
4556
4557
4558        if (!$paymentSuccess) {
4559            $this->log(__METHOD__ . ' aftee error --> ' . json_encode($checkRes) . ' --> ' . json_encode($params), $logFileName);
4560            return;
4561        }
4562
4563        // payment history data amount
4564        $reservationReceivableAmount = isset($ptParams['reservationReceivableAmount']) ? $ptParams['reservationReceivableAmount'] : 0;
4565        $appreciationReceivableAmount = isset($ptParams['appreciationReceivableAmount']) ? $ptParams['appreciationReceivableAmount'] : 0;
4566        $liveReceivableAmount = isset($ptParams['liveReceivableAmount']) ? $ptParams['liveReceivableAmount'] : 0;
4567
4568        // create payment
4569        $savePaymentArr = array(
4570            'user_id' => $child->id ?? (method_exists($child, 'getId') ? $child->getId() : null),
4571            'status' => 1,
4572            'reference_id' => $child->id ?? (method_exists($child, 'getId') ? $child->getId() : null),
4573            'payment_transaction_password' => $ptPassword,
4574            'card_company' => $cardCompany,
4575            'param1' => json_encode($checkRes),
4576            'form_type' => $formType,
4577            'ordd' => $paymentHash,
4578            'transaction_code' => $paymentHash,
4579            'currency_id' => $currencyId,
4580            'currency_code' => $currencyCode,
4581            'payment_id' => $paymentPlanId,
4582            'price_id' => $priceId,
4583            'payment_type' => $paymentType
4584        );
4585
4586        $this->Payment->clear();
4587        $this->Payment->create();
4588        $this->Payment->set($savePaymentArr);
4589        $this->Payment->validate = array();
4590
4591        // update/add user`s settlement amount
4592        $this->User->updateUserPayments($savePaymentArr);
4593
4594        // set payment_id
4595        $paymentSaveID = $this->Payment->id;
4596        $data = array('payment_id' => $paymentSaveID);
4597        $paymentType = Configure::read('payment_types.payment_receivable');
4598
4599        // reservation receivable
4600        if ($reservationReceivableAmount > 0) {
4601            $savePaymentArr = array(
4602                'user_id' => $child->id,
4603                'amount' => $reservationReceivableAmount,
4604                'status' => 1,
4605                'type_id' => 1,
4606                'reference_id' => $child->id,
4607                'card_company' => $cardCompany,
4608                'param1' => json_encode($data),
4609                'form_type' => Configure::read('payment_credit_receivable'),
4610                'ordd' => $paymentHash,
4611                'transaction_code' => $paymentHash,
4612                'currency_id' => $currencyId,
4613                'currency_code' => $currencyCode,
4614                'payment_id' => $paymentPlanId,
4615                'price_id' => $priceId,
4616                'payment_type' => $paymentType
4617            );
4618
4619            // create new payment for reservation receivable
4620            $this->Payment->clear();
4621            $this->Payment->create();
4622            $this->Payment->set($savePaymentArr);
4623            if (!$this->Payment->save()) {
4624                $this->log(__METHOD__ . ' Failed to save payment data for reservation receivable.' . json_encode($savePaymentArr), $logFileName);
4625                return;
4626            }
4627
4628            // set payment_id
4629            $rrPaymentID = $this->Payment->id;
4630
4631            //update/add user`s settlement amount
4632            $this->User->updateUserPayments($savePaymentArr);
4633
4634            // set payment receivable statuses to 2 - received
4635            $this->PaymentReceivable->updateReceivableReservationPayment(
4636                $child->id,
4637                array(
4638                    'status' => 2,
4639                    'payment_id' => $rrPaymentID,
4640                    'payment_collection_date' => $dateTimeNow,
4641                    'card_company' => $cardCompany,
4642                    'payment_plan_id' => $paymentPlanId,
4643                    'membership_type_index' => $membershipStatusIndex
4644                ),
4645                array(
4646                    'PaymentReceivable.user_id' => $child->id,
4647                    'PaymentReceivable.status' => 0,
4648                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.reservation'),
4649                    'PaymentReceivable.created <=' => $dateTimeNow
4650                )
4651            );
4652        }
4653
4654        // appreciation receivable
4655        if ($appreciationReceivableAmount > 0) {
4656            $savePaymentArr = array(
4657                'user_id' => $child->id,
4658                'amount' => $appreciationReceivableAmount,
4659                'status' => 1,
4660                'type_id' => 1,
4661                'reference_id' => $child->id,
4662                'card_company' => $cardCompany,
4663                'param1' => json_encode($data),
4664                'form_type' => Configure::read('payment_credit_appreciation_receivable'),
4665                'ordd' => $paymentHash,
4666                'transaction_code' => $paymentHash,
4667                'currency_id' => $currencyId,
4668                'currency_code' => $currencyCode,
4669                'payment_id' => $paymentPlanId,
4670                'price_id' => $priceId,
4671                'payment_type' => $paymentType
4672            );
4673
4674            // create new payment for appreciation receivable
4675            $this->Payment->clear();
4676            $this->Payment->create();
4677            $this->Payment->set($savePaymentArr);
4678            if (!$this->Payment->save()) {
4679                $this->log(__METHOD__ . ' Failed to save payment data for appreciation receivable.' . json_encode($savePaymentArr), $logFileName);
4680                return;
4681            }
4682
4683            // set payment_id
4684            $arPaymentID = $this->Payment->id;
4685
4686            //update/add user`s settlement amount
4687            $this->User->updateUserPayments($savePaymentArr);
4688
4689            // set payment receivable statuses to 2 - received
4690            $this->PaymentReceivable->updateReceivableReservationPayment(
4691                $child->id,
4692                array(
4693                    'status' => 2,
4694                    'payment_id' => $arPaymentID,
4695                    'payment_collection_date' => $dateTimeNow,
4696                    'card_company' => $cardCompany,
4697                    'payment_plan_id' => $paymentPlanId,
4698                    'membership_type_index' => $membershipStatusIndex
4699                ),
4700                array(
4701                    'PaymentReceivable.user_id' => $child->id,
4702                    'PaymentReceivable.status' => 0,
4703                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.appreciation'),
4704                    'PaymentReceivable.created <=' => $dateTimeNow
4705                )
4706            );
4707        }
4708
4709        // live receivable
4710        if ($liveReceivableAmount > 0) {
4711            $savePaymentArr = array(
4712                'user_id' => $child->id,
4713                'amount' => $liveReceivableAmount,
4714                'status' => 1,
4715                'type_id' => 1,
4716                'reference_id' => $child->id,
4717                'card_company' => $cardCompany,
4718                'param1' => json_encode($data),
4719                'form_type' => Configure::read('payment_live_lesson_receivable'),
4720                'ordd' => $paymentHash,
4721                'transaction_code' => $paymentHash,
4722                'currency_id' => $currencyId,
4723                'currency_code' => $currencyCode,
4724                'payment_id' => $paymentPlanId,
4725                'price_id' => $priceId,
4726                'payment_type' => $paymentType
4727            );
4728
4729            // create new payment for live receivable
4730            $this->Payment->clear();
4731            $this->Payment->create();
4732            $this->Payment->set($savePaymentArr);
4733            if (!$this->Payment->save()) {
4734                $this->log(__METHOD__ . ' Failed to save payment data for live receivable.' . json_encode($savePaymentArr), $logFileName);
4735                return;
4736            }
4737
4738            // set payment_id
4739            $lrPaymentID = $this->Payment->id;
4740
4741            //update/add user`s settlement amount
4742            $this->User->updateUserPayments($savePaymentArr);
4743
4744            // set payment receivable statuses to 2 - received
4745            $this->PaymentReceivable->updateReceivableReservationPayment(
4746                $child->id,
4747                array(
4748                    'status' => 2,
4749                    'payment_id' => $lrPaymentID,
4750                    'payment_collection_date' => $dateTimeNow,
4751                    'card_company' => $cardCompany,
4752                    'payment_plan_id' => $paymentPlanId,
4753                    'membership_type_index' => $membershipStatusIndex
4754                ),
4755                array(
4756                    'PaymentReceivable.user_id' => $child->id,
4757                    'PaymentReceivable.status' => 0,
4758                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.live'),
4759                    'PaymentReceivable.created <=' => $dateTimeNow
4760                )
4761            );
4762        }
4763
4764        $fields = array('status' => 1);
4765        if (isset($checkRes)) {
4766            $fields['response_text'] = array('aftee' => $checkRes);
4767        }
4768
4769        // update payment transaction
4770        $this->PaymentTransaction->updateWPPaymentTransaction(array('id' => $ptId, 'fields' => $fields));
4771
4772        return 'success_order';
4773    }
4774
4775    /**
4776     * ~NJ-29078 - process child receivable payment 
4777     * @param array $userArr
4778     */
4779    public function processParentReceivablePayment($userArr = [])
4780    {
4781        $logFileName = 'family_plan';
4782        $curlPayment = "";
4783
4784        if (!$pt = $this->Payment->setUpWithdrawTransaction($userArr, $logFileName)) {
4785            return false;
4786        }
4787
4788        if (isset($pt['totalAmount']) && $pt['totalAmount'] == 0) {
4789            $this->log(__METHOD__ . ' No receivable to process' . json_encode($pt), $logFileName);
4790            $curlPayment = "success_order";
4791            return $curlPayment;
4792        }
4793
4794        $userObj = new UserTable($userArr);
4795
4796        if ($userObj->card_company == Configure::read('card_company.zeus')) {
4797            $data = array(
4798                'clientIp' => PaymentTable::getClientIpByCompanyId($userObj->card_company),
4799                'email' => $userObj->email,
4800                'sendId' => $userObj->id,
4801                'money' => $pt['totalAmount'],
4802                'paymentHash' => $pt['payment_hash']
4803            );
4804            // ~process
4805            $curlPayment = $this->ZCharge->charge_with_regsterd_card(json_encode($data));
4806            $curlPayment = PaymentTable::checkPaymentResult($curlPayment);
4807        } else if ($userObj->card_company == Configure::read('card_company.worldpay')) {
4808            $paymentMethodType = myTools::getWPPaymentMethodType($userObj->card_brand, 'payment');
4809            $merchantCode = myTools::getWPMerchantCode($paymentMethodType);
4810            $paymentHash = $pt['payment_hash'];
4811            $paymentMethod = explode('_', $paymentMethodType);
4812            $paymentMethod = isset($paymentMethod[0]) ? $paymentMethod[0] : null;
4813            $currencyExponents = Configure::read('worldpay.currency_exponents');
4814            $exponent = $currencyExponents[$userObj->currency_code];
4815            // get amount with checking currency exponent
4816            $amountArr = myTools::wpGetAmount($exponent, $pt['totalAmount']);
4817            $wpAmount = $amountArr['wpAmount'];
4818
4819            $decodePaymentParams = json_decode($pt['payment_params']);
4820            $paymentFormType = $decodePaymentParams->formType;
4821
4822            $wpParams = array(
4823                'merchantCode' => $merchantCode,
4824                'orderCode' => $paymentHash,
4825                'description' => 'Child Withdrawal Receivables',
4826                'currencyCode' => $userObj->currency_code,
4827                'exponent' => $exponent,
4828                'amount' => $wpAmount,
4829                'cardToken' => $userObj->card_token,
4830                'email' => $userObj->email,
4831                'authenticatedShopperId' => $userObj->id,
4832                'xmlName' => 'direct_payment_with_token',
4833                'shopperIpAddress' => $_SERVER["REMOTE_ADDR"],
4834                'wpTransactionIdentifier' => $userObj->wp_transaction_identifier,
4835                'paymentMethod' => $paymentMethod
4836            );
4837
4838            $updateData = array(
4839                'id' => $pt['id'],
4840                'fields' => array('payment_params' => $wpParams)
4841            );
4842
4843            if (!$this->PaymentTransaction->updateWPPaymentTransaction($updateData)) {
4844                $this->log(__METHOD__ . ' Failed to update payment transaction' . json_encode($updateData), $logFileName);
4845            } else {
4846                if (!$pt = $this->PaymentTransaction->getWPPaymentTransaction($paymentHash)) {
4847                    return false;
4848                }
4849            }
4850
4851            // ~process
4852            $res = wpPaymentService::directPayment($wpParams);
4853
4854            $updateData = array(
4855                'id' => $pt['id'],
4856                'fields' => array('response_text' => array('directPayment_response' => $res))
4857            );
4858
4859            if (!$this->PaymentTransaction->updateWPPaymentTransaction($updateData)) {
4860                $this->log(__METHOD__ . ' Failed to update payment transaction' . json_encode($updateData), $logFileName);
4861            }
4862
4863            if (!myTools::checkIfWPPaymentResponseIsAuthorised($res)) {
4864                $curlPayment = "";
4865                $this->log(__METHOD__ . ' Not authorised payment worldpay' . $userObj->id, $logFileName);
4866            } else {
4867                $curlPayment = "success_order";
4868            }
4869        } else if ($userObj->card_company == Configure::read('card_company.aftee')) {
4870            $paymentMethodType = myTools::getWPPaymentMethodType($userObj->card_brand, 'payment');
4871            $merchantCode = myTools::getWPMerchantCode($paymentMethodType);
4872            $paymentHash = $pt['payment_hash'];
4873            $paymentMethod = explode('_', $paymentMethodType);
4874            $paymentMethod = isset($paymentMethod[0]) ? $paymentMethod[0] : null;
4875            $decodePaymentParams = json_decode($pt['payment_params']);
4876            $paymentFormType = $decodePaymentParams->formType;
4877
4878            $afteeParams = array(
4879                'merchantCode' => $merchantCode,
4880                'orderCode' => $paymentHash,
4881                'description' => 'Family Plan Registration',
4882                'currencyCode' => $userObj->currency_code,
4883                'amount' => $pt['totalAmount'],
4884                'cardToken' => $userObj->card_token,
4885                'email' => $userObj->email,
4886                'authenticatedShopperId' => $userObj->id,
4887                'shopperIpAddress' => $_SERVER["REMOTE_ADDR"],
4888                'afteeTransactionIdentifier' => $userObj->aftee_transaction_identifier,
4889                'paymentMethod' => $paymentMethod
4890            );
4891
4892            $updateData = array(
4893                'id' => $pt['id'],
4894                'fields' => array('payment_params' => $afteeParams)
4895            );
4896
4897            if (!$this->PaymentTransaction->updateAfteePaymentTransaction($updateData)) {
4898                $this->log(__METHOD__ . ' Failed to update payment transaction' . json_encode($updateData), $logFileName);
4899            } else {
4900                if (!$pt = $this->PaymentTransaction->getAfteePaymentTransaction($paymentHash)) {
4901                    return false;
4902                }
4903            }
4904
4905            // ~process
4906            $afteeParams = array(
4907                'user' =>  $userObj,
4908                'paymentTransaction' => $pt,
4909                'appreciationFlg' => $userObj->allow_appreciation_flg,
4910                'tipAmount' => myTools::stringToFloat($userObj->tip_max_amount)
4911            );
4912
4913            $curlPayment = $this->processParentAfteePayment($afteeParams);
4914        } elseif ($userObj->card_company == Configure::read('card_company.paypal')) {
4915            $paypalParams = array(
4916                'user' => $userObj,
4917                'paymentTransaction' => $pt,
4918                'memberStatus' => 'exist'
4919            );
4920
4921            $curlPayment = $this->processParentPaypalPayment($paypalParams);
4922        } else if ($userObj->card_company == Configure::read('card_company.stripe.apple') || $userObj->card_company == Configure::read('card_company.stripe.google')){
4923            if (!class_exists('Stripe')) {
4924                App::import('Lib', 'Stripe');
4925            }
4926
4927            $data = array(
4928                'customerId' => $userObj->stripe_customer_id,
4929                'amount' => $pt['totalAmount'],
4930                'currency' => $userObj->currency_code,
4931                'paymentMethodID' => $userObj->stripe_payment_identifier,
4932                'description' => 'Family Plan Receivable Payment',
4933                'sendpoint' => $pt['payment_hash'],
4934                'sendid' => $userObj->id,
4935                'card_company' => $userObj->card_company
4936            );
4937            
4938            $stripe = new Stripe();
4939            $curlPayment = $stripe->directPayment($data);    
4940            $curlPayment = myTools::checkStripePaymentResponse($curlPayment);
4941
4942        }
4943
4944        return $curlPayment;
4945    }
4946
4947    // ~NJ-29078 - Withdraw Paypal Process Payment
4948    private function processParentPaypalPayment($params = array())
4949    {
4950        $logFileName = 'family_plan';
4951        if (
4952            !isset($params['user']) ||
4953            !isset($params['paymentTransaction'])
4954        ) {
4955            $this->log('__METHOD__' . ' missing parameter(s). --> ' . json_encode($params), $logFileName);
4956            return false;
4957        }
4958
4959        // ~check for family parent 
4960        $user = $params['user'];
4961        $pt = $params['paymentTransaction'];
4962        $memberStatus = $params['memberStatus'];
4963        $paymentHash = $pt['payment_hash'] ?? null;
4964        $ptPassword = $pt['password'] ?? '';
4965        $ptParams = json_decode($pt['payment_params'] ?? '', true);
4966
4967        $formType = $ptParams['formType'] ?? null;
4968        $currencyCode = $ptParams['currencyCode'] ?? null;
4969        $paymentPlanId = $ptParams['paymentPlanId'] ?? null;
4970        $priceId = $ptParams['priceId'] ?? null;
4971        $paymentType = Configure::read('payment_types.payment_receivable');
4972        $platform = $ptParams['platform'] ?? null;
4973
4974        $membershipStatusIndex = UserTable::getStudentMembershipStatus(method_exists($user, 'getId') ? $user->getId() : (isset($user->id) ? $user->id : null));
4975        $currencyId = Configure::read('default.settlement_currency_id'); // set currency id to jpy
4976        $cardCompany = Configure::read('card_company.paypal');
4977        $dateTimeNow = date('Y-m-d H:i:s');
4978
4979        $reservationReceivableAmount = isset($ptParams['reservationReceivableAmount']) ? $ptParams['reservationReceivableAmount'] : 0;
4980        $appreciationReceivableAmount = isset($ptParams['appreciationReceivableAmount']) ? $ptParams['appreciationReceivableAmount'] : 0;
4981        $liveReceivableAmount = isset($ptParams['liveReceivableAmount']) ? $ptParams['liveReceivableAmount'] : 0;
4982
4983
4984        if (!class_exists('PayPal')) {
4985            App::import('Lib', 'PayPal');
4986        }
4987
4988        $PayPal = new PayPal();
4989        $accessTokenData = $PayPal->getAccessToken();
4990
4991        $totalAmount = (int) ($reservationReceivableAmount + $appreciationReceivableAmount + $liveReceivableAmount);
4992
4993        $paypalParams = array(
4994            'ptId' => $pt['id'],
4995            'paypalData' => array('accessTokenData' => $accessTokenData),
4996            'userId' => method_exists($user, 'getId') ? $user->getId() : ($user->id ?? null),
4997            'money' => $totalAmount,
4998            'formType' => $formType,
4999            'priceId' => $priceId,
5000            'paymentId' => $paymentPlanId,
5001            'paymentType' => $paymentType
5002        );
5003
5004        $receivables = [
5005            'payment_credit_receivable' => $reservationReceivableAmount,
5006            'payment_credit_appreciation_receivable' => $appreciationReceivableAmount,
5007            'payment_live_lesson_receivable' => $liveReceivableAmount
5008        ];
5009
5010        // break if error
5011        if (!isset($accessTokenData['access_token'])) {
5012            $this->log(__METHOD__ . ' paypal error --> ' . json_encode($accessTokenData) . ' --> ' . json_encode($params), $logFileName);
5013            $this->savePaypalFailedSettlement($receivables, $paypalParams);
5014            return;
5015        }
5016
5017        $createOrderParams = array(
5018            'accessToken' => $accessTokenData['access_token'],
5019            'paypalRequestId' => $pt['id'],
5020            'intent' => 'CAPTURE',
5021            'paymentHash' => $paymentHash,
5022            'userId' => $user->id ?? null,
5023            'currencyCode' => $currencyCode,
5024            'amount' => $totalAmount,
5025            'billingAgreementId' => $user->paypal_billing_agreement_id ?? null
5026        );
5027
5028        // add mock application code
5029        if (isset($request['mockResponse'])) {
5030            $createOrderParams['mockResponse'] = $request['mockResponse'];
5031        }
5032
5033        $curlPayment = $PayPal->createOrder($createOrderParams);
5034        $paypalParams['paypalData']['createOrder'] = $curlPayment;
5035        $paymentSuccess = isset($curlPayment['status']) && $curlPayment['status'] == 'COMPLETED' ? true : false;
5036
5037        if (!$paymentSuccess) {
5038            //$this->log(__METHOD__ . ' paypal error --> ' . json_encode($curlPayment) . ' --> ' . json_encode($params), $logFileName);
5039            $this->savePaypalFailedSettlement($receivables, $paypalParams);
5040            return;
5041        }
5042
5043        // create payment
5044        $savePaymentArr = array(
5045            'user_id' => $user->id ?? null,
5046            'amount' => $totalAmount,
5047            'status' => 1,
5048            'reference_id' => $user->id ?? null,
5049            'payment_transaction_password' => $ptPassword,
5050            'card_company' => $cardCompany,
5051            'param1' => json_encode($paypalParams),
5052            'form_type' => $formType,
5053            'ordd' => $paymentHash,
5054            'transaction_code' => $paymentHash,
5055            'currency_id' => $currencyId,
5056            'currency_code' => $currencyCode,
5057            'payment_id' => $paymentPlanId,
5058            'price_id' => $priceId,
5059            'payment_type' => $paymentType
5060        );
5061
5062        $this->Payment->clear();
5063        $this->Payment->create();
5064        $this->Payment->set($savePaymentArr);
5065        $this->Payment->validate = array();
5066
5067        // update/add user`s settlement amount
5068        $this->User->updateUserPayments($savePaymentArr);
5069
5070        // set payment_id
5071        $paymentSaveID = $this->Payment->id;
5072        $data = array('payment_id' => $paymentSaveID);
5073        $paymentType = Configure::read('payment_types.payment_receivable');
5074
5075        // reservation receivable
5076        if ($reservationReceivableAmount > 0) {
5077            $savePaymentArr = array(
5078                'user_id' => $user->id,
5079                'amount' => $reservationReceivableAmount,
5080                'status' => 1,
5081                'type_id' => 1,
5082                'reference_id' => $user->id,
5083                'card_company' => $cardCompany,
5084                'param1' => json_encode($data),
5085                'form_type' => Configure::read('payment_credit_receivable'),
5086                'ordd' => $paymentHash,
5087                'transaction_code' => $paymentHash,
5088                'currency_id' => $currencyId,
5089                'currency_code' => $currencyCode,
5090                'payment_id' => $paymentPlanId,
5091                'price_id' => $priceId,
5092                'payment_type' => $paymentType
5093            );
5094
5095            // create new payment for reservation receivable
5096            $this->Payment->clear();
5097            $this->Payment->create();
5098            $this->Payment->set($savePaymentArr);
5099            if (!$this->Payment->save()) {
5100                //$this->log(__METHOD__ . ' Failed to save payment data for reservation receivable.' . json_encode($savePaymentArr), $logFileName);
5101                return;
5102            }
5103
5104            // set payment_id
5105            $rrPaymentID = $this->Payment->id;
5106
5107            //update/add user`s settlement amount
5108            $this->User->updateUserPayments($savePaymentArr);
5109
5110            // set payment receivable statuses to 2 - received
5111            $this->PaymentReceivable->updateReceivableReservationPayment(
5112                $user->id,
5113                array(
5114                    'status' => 2,
5115                    'payment_id' => $rrPaymentID,
5116                    'payment_collection_date' => $dateTimeNow,
5117                    'card_company' => $cardCompany,
5118                    'payment_plan_id' => $paymentPlanId,
5119                    'membership_type_index' => $membershipStatusIndex
5120                ),
5121                array(
5122                    'PaymentReceivable.user_id' => $user->id,
5123                    'PaymentReceivable.status' => 0,
5124                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.reservation'),
5125                    'PaymentReceivable.created <=' => $dateTimeNow
5126                )
5127            );
5128        }
5129
5130        // appreciation receivable
5131        if ($appreciationReceivableAmount > 0) {
5132            $savePaymentArr = array(
5133                'user_id' => $user->id,
5134                'amount' => $appreciationReceivableAmount,
5135                'status' => 1,
5136                'type_id' => 1,
5137                'reference_id' => $user->id,
5138                'card_company' => $cardCompany,
5139                'param1' => json_encode($data),
5140                'form_type' => Configure::read('payment_credit_appreciation_receivable'),
5141                'ordd' => $paymentHash,
5142                'transaction_code' => $paymentHash,
5143                'currency_id' => $currencyId,
5144                'currency_code' => $currencyCode,
5145                'payment_id' => $paymentPlanId,
5146                'price_id' => $priceId,
5147                'payment_type' => $paymentType
5148            );
5149
5150            // create new payment for appreciation receivable
5151            $this->Payment->clear();
5152            $this->Payment->create();
5153            $this->Payment->set($savePaymentArr);
5154            if (!$this->Payment->save()) {
5155                $this->log(__METHOD__ . ' Failed to save payment data for appreciation receivable.' . json_encode($savePaymentArr), $logFileName);
5156                return;
5157            }
5158
5159            // set payment_id
5160            $arPaymentID = $this->Payment->id;
5161
5162            //update/add user`s settlement amount
5163            $this->User->updateUserPayments($savePaymentArr);
5164
5165            // set payment receivable statuses to 2 - received
5166            $this->PaymentReceivable->updateReceivableReservationPayment(
5167                $user->id,
5168                array(
5169                    'status' => 2,
5170                    'payment_id' => $arPaymentID,
5171                    'payment_collection_date' => $dateTimeNow,
5172                    'card_company' => $cardCompany,
5173                    'payment_plan_id' => $paymentPlanId,
5174                    'membership_type_index' => $membershipStatusIndex
5175                ),
5176                array(
5177                    'PaymentReceivable.user_id' => $user->id,
5178                    'PaymentReceivable.status' => 0,
5179                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.appreciation'),
5180                    'PaymentReceivable.created <=' => $dateTimeNow
5181                )
5182            );
5183        }
5184
5185        // live receivable
5186        if ($liveReceivableAmount > 0) {
5187            $savePaymentArr = array(
5188                'user_id' => $user->id,
5189                'amount' => $liveReceivableAmount,
5190                'status' => 1,
5191                'type_id' => 1,
5192                'reference_id' => $user->id,
5193                'card_company' => $cardCompany,
5194                'param1' => json_encode($data),
5195                'form_type' => Configure::read('payment_live_lesson_receivable'),
5196                'ordd' => $paymentHash,
5197                'transaction_code' => $paymentHash,
5198                'currency_id' => $currencyId,
5199                'currency_code' => $currencyCode,
5200                'payment_id' => $paymentPlanId,
5201                'price_id' => $priceId,
5202                'payment_type' => $paymentType
5203            );
5204
5205            // create new payment for live receivable
5206            $this->Payment->clear();
5207            $this->Payment->create();
5208            $this->Payment->set($savePaymentArr);
5209            if (!$this->Payment->save()) {
5210                $this->log(__METHOD__ . ' Failed to save payment data for live receivable.' . json_encode($savePaymentArr), $logFileName);
5211                return;
5212            }
5213
5214            // set payment_id
5215            $lrPaymentID = $this->Payment->id;
5216
5217            //update/add user`s settlement amount
5218            $this->User->updateUserPayments($savePaymentArr);
5219
5220            // set payment receivable statuses to 2 - received
5221            $this->PaymentReceivable->updateReceivableReservationPayment(
5222                $user->id,
5223                array(
5224                    'status' => 2,
5225                    'payment_id' => $lrPaymentID,
5226                    'payment_collection_date' => $dateTimeNow,
5227                    'card_company' => $cardCompany,
5228                    'payment_plan_id' => $paymentPlanId,
5229                    'membership_type_index' => $membershipStatusIndex
5230                ),
5231                array(
5232                    'PaymentReceivable.user_id' => $user->id,
5233                    'PaymentReceivable.status' => 0,
5234                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.live'),
5235                    'PaymentReceivable.created <=' => $dateTimeNow
5236                )
5237            );
5238        }
5239
5240        $fields = array('status' => 1);
5241        if (isset($paypalParams)) {
5242            $fields['response_text'] = array('paypal_response' => $paypalParams);
5243        }
5244
5245        // update payment transaction
5246        $this->PaymentTransaction->updateWPPaymentTransaction(array('id' => $ptId ?? null, 'fields' => $fields));
5247        return 'success_order';
5248    }
5249
5250    private function savePaypalFailedSettlement($receivables = array(), $paypalParams = array()) {
5251        if ($receivables && $paypalParams) {
5252            foreach ($receivables as $configKey => $amount) {
5253                if ($amount > 0) {
5254                    $paypalParams['formType'] = Configure::read($configKey);
5255                    $paypalParams['money'] = $amount;
5256                    
5257                    $this->Payment->paypalSaveFailedSettlement($paypalParams);
5258                }
5259            }
5260        }
5261    }
5262
5263    // ~NJ-29078 - Withdraw Aftee Process Payment
5264    private function processParentAfteePayment($params = array())
5265    {
5266        $logFileName = 'family_plan';
5267        if (
5268            !isset($params['user']) ||
5269            !isset($params['paymentTransaction'])
5270        ) {
5271            $this->log('__METHOD__' . ' missing parameter(s). --> ' . json_encode($params), $logFileName);
5272            return false;
5273        }
5274
5275        $user = $params['user'];
5276        $pt = $params['paymentTransaction'];
5277
5278        $ptId = $pt['id'];
5279        $ptPassword = isset($pt['password']) ? $pt['password'] : '';
5280        $ptParams = json_decode($pt['payment_params'], true);
5281
5282        $formType = $ptParams['formType'] ?? null;
5283        $currencyCode = $ptParams['currencyCode'] ?? null;
5284        $paymentPlanId = $ptParams['paymentPlanId'] ?? null;
5285        $priceId = $ptParams['priceId'] ?? null;
5286        $paymentType = $ptParams['paymentType'] ?? null;
5287        $platform = $ptParams['platform'] ?? null;
5288        $paymentHash = $ptParams['orderCode'] ?? null;
5289        $afteeTransactionIdentifier = $ptParams['afteeTransactionIdentifier'] ?? null;
5290
5291        $membershipStatusIndex = UserTable::getStudentMembershipStatus($user->id);
5292        $currencyId = Configure::read('default.settlement_currency_id'); // set currency id to jpy
5293        $cardCompany = Configure::read('card_company.aftee');
5294        $dateTimeNow = date('Y-m-d H:i:s');
5295
5296        $appreciationFlg = 0;
5297        // $this->log(__METHOD__ . ' aftee debug --> ' . json_encode($params), $logFileName);
5298        // $this->log(__METHOD__ . ' aftee debug --> ' . json_encode($pt), $logFileName);
5299        // $this->log(__METHOD__ . ' aftee debug --> ' . $paymentHash, $logFileName);
5300
5301        // initial aftee amount
5302        $totalAmount = (int)($ptParams['paymentAmount'] ?? 0);
5303
5304        if ($totalAmount > 0) {
5305            if (isset($user->aftee_transaction_identifier) && !empty($user->aftee_transaction_identifier)) {
5306                $related_id = $user->aftee_transaction_identifier;
5307            } else {
5308                $related_id = $afteeTransactionIdentifier;
5309            }
5310
5311            // load PayPal class
5312            if (!class_exists('AfteePaymentService')) {
5313                App::import('Lib', 'AfteePaymentService');
5314            }
5315
5316            $afteeChecksumData = array(
5317                'shopItemId' => "AFTEE" . $formType,
5318                'itemName' => 'FamilyPlanRegistration',
5319                'itemPrice' => $totalAmount,
5320                'itemCount' => 1,
5321                'customerPhoneNumber' => $user->phone_number,
5322                'customerEmail' => $user->email,
5323                'shopTransactionNo' => $paymentHash,
5324                'userID' => $user->id
5325            );
5326            $afteeService = new AfteePaymentService();
5327            $checksum = $afteeService->generateChecksum($afteeChecksumData, false);
5328
5329
5330            $afteeData = array(
5331                'authentication_token' => $user->card_token,
5332                'related_id' => $related_id,
5333                'checksum' => $checksum['checksum'],
5334                'shop_transaction_no' => $paymentHash,
5335                'transaction_options' => array(1)
5336            );
5337
5338            $afteePaymentData = array_merge($afteeData, $checksum['settlementData']);
5339
5340            // process Aftee direct payment
5341            $res = $afteeService->directPayment($afteePaymentData);
5342            $checkRes = json_decode($res, true);
5343            //$this->log(__METHOD__ . ' aftee --> ' . json_encode($afteePaymentData) . ' --> ' . json_encode($checkRes), $logFileName);
5344
5345            if (isset($checkRes['object']) && $checkRes['object'] == 'transaction') {
5346                $paymentSuccess = true;
5347            } else if (!array_key_exists("object", $checkRes) || (isset($checkRes['object']) && $checkRes['object'] == 'error')) {
5348                $paymentSuccess = false;
5349            }
5350        } else {
5351            // zero payment
5352            $checkRes = array('aftee zero payment --> family plan registration');
5353            $paymentSuccess = true;
5354        }
5355
5356        if (!$paymentSuccess) {
5357            $this->log(__METHOD__ . ' aftee error --> ' . json_encode($checkRes) . ' --> ' . json_encode($params), $logFileName);
5358            return;
5359        }
5360
5361        // payment history data amount
5362        $reservationReceivableAmount = isset($ptParams['reservationReceivableAmount']) ? $ptParams['reservationReceivableAmount'] : 0;
5363        $appreciationReceivableAmount = isset($ptParams['appreciationReceivableAmount']) ? $ptParams['appreciationReceivableAmount'] : 0;
5364        $liveReceivableAmount = isset($ptParams['liveReceivableAmount']) ? $ptParams['liveReceivableAmount'] : 0;
5365
5366        // create payment
5367        $savePaymentArr = array(
5368            'user_id' => $user->id,
5369            'status' => 1,
5370            'reference_id' => $user->id,
5371            'payment_transaction_password' => $ptPassword,
5372            'card_company' => $cardCompany,
5373            'param1' => json_encode($checkRes),
5374            'form_type' => $formType,
5375            'ordd' => $paymentHash,
5376            'transaction_code' => $paymentHash,
5377            'currency_id' => $currencyId,
5378            'currency_code' => $currencyCode,
5379            'payment_id' => $paymentPlanId,
5380            'price_id' => $priceId,
5381            'payment_type' => $paymentType
5382        );
5383
5384        $this->Payment->clear();
5385        $this->Payment->create();
5386        $this->Payment->set($savePaymentArr);
5387        $this->Payment->validate = array();
5388
5389        // update/add user`s settlement amount
5390        $this->User->updateUserPayments($savePaymentArr);
5391
5392        // set payment_id
5393        $paymentSaveID = $this->Payment->id;
5394        $data = array('payment_id' => $paymentSaveID);
5395        $paymentType = Configure::read('payment_types.payment_receivable');
5396
5397        // reservation receivable
5398        if ($reservationReceivableAmount > 0) {
5399            $savePaymentArr = array(
5400                'user_id' => $user->id,
5401                'amount' => $reservationReceivableAmount,
5402                'status' => 1,
5403                'type_id' => 1,
5404                'reference_id' => $user->id,
5405                'card_company' => $cardCompany,
5406                'param1' => json_encode($data),
5407                'form_type' => Configure::read('payment_credit_receivable'),
5408                'ordd' => $paymentHash,
5409                'transaction_code' => $paymentHash,
5410                'currency_id' => $currencyId,
5411                'currency_code' => $currencyCode,
5412                'payment_id' => $paymentPlanId,
5413                'price_id' => $priceId,
5414                'payment_type' => $paymentType
5415            );
5416
5417            // create new payment for reservation receivable
5418            $this->Payment->clear();
5419            $this->Payment->create();
5420            $this->Payment->set($savePaymentArr);
5421            if (!$this->Payment->save()) {
5422                $this->log(__METHOD__ . ' Failed to save payment data for reservation receivable.' . json_encode($savePaymentArr), $logFileName);
5423                return;
5424            }
5425
5426            // set payment_id
5427            $rrPaymentID = $this->Payment->id;
5428
5429            //update/add user`s settlement amount
5430            $this->User->updateUserPayments($savePaymentArr);
5431
5432            // set payment receivable statuses to 2 - received
5433            $this->PaymentReceivable->updateReceivableReservationPayment(
5434                $user->id,
5435                array(
5436                    'status' => 2,
5437                    'payment_id' => $rrPaymentID,
5438                    'payment_collection_date' => $dateTimeNow,
5439                    'card_company' => $cardCompany,
5440                    'payment_plan_id' => $paymentPlanId,
5441                    'membership_type_index' => $membershipStatusIndex
5442                ),
5443                array(
5444                    'PaymentReceivable.user_id' => $user->id,
5445                    'PaymentReceivable.status' => 0,
5446                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.reservation'),
5447                    'PaymentReceivable.created <=' => $dateTimeNow
5448                )
5449            );
5450        }
5451
5452        // appreciation receivable
5453        if ($appreciationReceivableAmount > 0) {
5454            $savePaymentArr = array(
5455                'user_id' => $user->id,
5456                'amount' => $appreciationReceivableAmount,
5457                'status' => 1,
5458                'type_id' => 1,
5459                'reference_id' => $user->id,
5460                'card_company' => $cardCompany,
5461                'param1' => json_encode($data),
5462                'form_type' => Configure::read('payment_credit_appreciation_receivable'),
5463                'ordd' => $paymentHash,
5464                'transaction_code' => $paymentHash,
5465                'currency_id' => $currencyId,
5466                'currency_code' => $currencyCode,
5467                'payment_id' => $paymentPlanId,
5468                'price_id' => $priceId,
5469                'payment_type' => $paymentType
5470            );
5471
5472            // create new payment for appreciation receivable
5473            $this->Payment->clear();
5474            $this->Payment->create();
5475            $this->Payment->set($savePaymentArr);
5476            if (!$this->Payment->save()) {
5477                $this->log(__METHOD__ . ' Failed to save payment data for appreciation receivable.' . json_encode($savePaymentArr), $logFileName);
5478                return;
5479            }
5480
5481            // set payment_id
5482            $arPaymentID = $this->Payment->id;
5483
5484            //update/add user`s settlement amount
5485            $this->User->updateUserPayments($savePaymentArr);
5486
5487            // set payment receivable statuses to 2 - received
5488            $this->PaymentReceivable->updateReceivableReservationPayment(
5489                $user->id,
5490                array(
5491                    'status' => 2,
5492                    'payment_id' => $arPaymentID,
5493                    'payment_collection_date' => $dateTimeNow,
5494                    'card_company' => $cardCompany,
5495                    'payment_plan_id' => $paymentPlanId,
5496                    'membership_type_index' => $membershipStatusIndex
5497                ),
5498                array(
5499                    'PaymentReceivable.user_id' => $user->id,
5500                    'PaymentReceivable.status' => 0,
5501                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.appreciation'),
5502                    'PaymentReceivable.created <=' => $dateTimeNow
5503                )
5504            );
5505        }
5506
5507        // live receivable
5508        if ($liveReceivableAmount > 0) {
5509            $savePaymentArr = array(
5510                'user_id' => $user->id,
5511                'amount' => $liveReceivableAmount,
5512                'status' => 1,
5513                'type_id' => 1,
5514                'reference_id' => $user->id,
5515                'card_company' => $cardCompany,
5516                'param1' => json_encode($data),
5517                'form_type' => Configure::read('payment_live_lesson_receivable'),
5518                'ordd' => $paymentHash,
5519                'transaction_code' => $paymentHash,
5520                'currency_id' => $currencyId,
5521                'currency_code' => $currencyCode,
5522                'payment_id' => $paymentPlanId,
5523                'price_id' => $priceId,
5524                'payment_type' => $paymentType
5525            );
5526
5527            // create new payment for live receivable
5528            $this->Payment->clear();
5529            $this->Payment->create();
5530            $this->Payment->set($savePaymentArr);
5531            if (!$this->Payment->save()) {
5532                $this->log(__METHOD__ . ' Failed to save payment data for live receivable.' . json_encode($savePaymentArr), $logFileName);
5533                return;
5534            }
5535
5536            // set payment_id
5537            $lrPaymentID = $this->Payment->id;
5538
5539            //update/add user`s settlement amount
5540            $this->User->updateUserPayments($savePaymentArr);
5541
5542            // set payment receivable statuses to 2 - received
5543            $this->PaymentReceivable->updateReceivableReservationPayment(
5544                $user->id,
5545                array(
5546                    'status' => 2,
5547                    'payment_id' => $lrPaymentID,
5548                    'payment_collection_date' => $dateTimeNow,
5549                    'card_company' => $cardCompany,
5550                    'payment_plan_id' => $paymentPlanId,
5551                    'membership_type_index' => $membershipStatusIndex
5552                ),
5553                array(
5554                    'PaymentReceivable.user_id' => $user->id,
5555                    'PaymentReceivable.status' => 0,
5556                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.live'),
5557                    'PaymentReceivable.created <=' => $dateTimeNow
5558                )
5559            );
5560        }
5561
5562        $fields = array('status' => 1);
5563        if (isset($checkRes)) {
5564            $fields['response_text'] = array('aftee' => $checkRes);
5565        }
5566
5567        // update payment transaction
5568        $this->PaymentTransaction->updateWPPaymentTransaction(array('id' => $ptId, 'fields' => $fields));
5569
5570        return 'success_order';
5571    }
5572
5573    protected function checkCompanyIPForSMS($userId) {
5574        $userIp = $_SERVER['REMOTE_ADDR'];
5575        
5576        $this->InhouseIp->openDBReplica();
5577
5578        $checkCompanyIp = $this->InhouseIp->find('first', array(
5579            'conditions' => array(
5580                'ip_address' => $userIp,
5581                'status' => 1
5582            ),
5583        ));
5584
5585        $this->InhouseIp->closeDBReplica();
5586    
5587        if (!empty($checkCompanyIp)) {
5588            $sms_through_flg = array('sms_through_flg' => 1);
5589            $this->User->updateUserById(array('userData' => $sms_through_flg, 'id' => $userId));
5590            return true;
5591        }
5592
5593        return false;
5594    }
5595
5596    protected function setPerMonthSymbol($language = null, $addDivider = false) {
5597        $allowedLanguages = Configure::read('allowed_currencies');
5598
5599        $perMonthSymbol =  __dx('register', 'month', '月');
5600        $dividerCurrencyCode = Configure::read('currency_jpy');
5601        if (in_array($language, $allowedLanguages) && $language == Configure::read('language_ptbr')) {
5602            $dividerCurrencyCode = Configure::read('currency_brl');
5603            $perMonthSymbol =  __d('register', '毎月');
5604        }
5605
5606        if ($addDivider) {
5607            $perMonthSymbol = myTools::getPriceMonthlyDivider($dividerCurrencyCode) . $perMonthSymbol;
5608        }
5609
5610        $this->set('perMonthSymbol', $perMonthSymbol);
5611    }
5612
5613    public function corporateIpRestrictionLogout()
5614    {
5615        $this->Auth->flash(__d("login", "このアカウントは指定された場所でのみ利用可能です"));
5616        $this->Auth->logout();
5617        return $this->redirect(myTools::getUrl() . '/login');
5618    }
5619
5620}